diff --git a/docs/allocation_profiling.md b/docs/allocation_profiling.md new file mode 100644 index 0000000..00e3451 --- /dev/null +++ b/docs/allocation_profiling.md @@ -0,0 +1,89 @@ +# Поиск лишних аллокаций + +Для анализа аллокаций в задачах с бенчмарками удобно использовать встроенный в язык профайлер `pprof`. + +Сперва нужно запустить бенчмарк с профайлером +``` +✗ go test -v -run=^$ -bench=BenchmarkSprintf -tags private,solution -memprofile=mem.out ./varfmt/... +goos: linux +goarch: amd64 +pkg: gitlab.com/slon/shad-go/varfmt +cpu: Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz +BenchmarkSprintf +BenchmarkSprintf/small +BenchmarkSprintf/small-8 19429222 62.93 ns/op 2 B/op 1 allocs/op +BenchmarkSprintf/small_string +BenchmarkSprintf/small_string-8 13282659 84.48 ns/op 16 B/op 1 allocs/op +BenchmarkSprintf/big +BenchmarkSprintf/big-8 20089 62372 ns/op 16388 B/op 1 allocs/op +PASS +ok gitlab.com/slon/shad-go/varfmt 4.363s +``` + +Сэмплы профайлера будут записаны в бинарный файл `mem.out`. + +Этот файл можно открыть командой +``` +✗ go tool pprof mem.out +File: varfmt.test +Type: alloc_space +Time: Mar 14, 2023 at 9:07pm (MSK) +Entering interactive mode (type "help" for commands, "o" for options) +(pprof) +``` + +В результате откроется интерактивная среда, в которой есть всякие команды, например `help`. + +Чтобы узнать как запускать конкретную команду нужно вызвать `help` для неё +``` +(pprof) help top +Outputs top entries in text form + Usage: + top [n] [focus_regex]* [-ignore_regex]* [-cum] >f + Include up to n samples + Include samples matching focus_regex, and exclude ignore_regex. + -cum sorts the output by cumulative weight + Optionally save the report on the file f +``` + +Команда `top` покажет места, где суммарно было больше всего аллокаций +``` +(pprof) top -cum +Showing nodes accounting for 715.73MB, 99.37% of 720.23MB total +Dropped 24 nodes (cum <= 3.60MB) + flat flat% sum% cum cum% + 715.73MB 99.37% 99.37% 716.73MB 99.51% fmt.Sprintf + 0 0% 99.37% 716.73MB 99.51% gitlab.com/slon/shad-go/varfmt.BenchmarkSprintf.func1 + 0 0% 99.37% 716.73MB 99.51% testing.(*B).launch + 0 0% 99.37% 716.73MB 99.51% testing.(*B).runN +(pprof) +``` + +Команда `svg` сдампит `top` в картинку. + +``` +(pprof) svg +Generating report in profile001.svg +``` + +Команда `list` покажет строчки, в которых происходят аллокации +``` +(pprof) list fmt.Sprintf +Total: 720.23MB +ROUTINE ======================== fmt.Sprintf in /usr/local/go/src/fmt/print.go + 715.73MB 716.73MB (flat, cum) 99.51% of Total + . . 213: return Fprintf(os.Stdout, format, a...) + . . 214:} + . . 215: + . . 216:// Sprintf formats according to a format specifier and returns the resulting string. + . . 217:func Sprintf(format string, a ...any) string { + . 512kB 218: p := newPrinter() + . . 219: p.doPrintf(format, a) + 715.73MB 715.73MB 220: s := string(p.buf) + . 512.50kB 221: p.free() + . . 222: return s + . . 223:} + . . 224: + . . 225:// Appendf formats according to a format specifier, appends the result to the byte + . . 226:// slice, and returns the updated slice. +``` diff --git a/utf8/README.md b/utf8/README.md index 56f2591..bc62692 100644 --- a/utf8/README.md +++ b/utf8/README.md @@ -3,3 +3,10 @@ Задача объединяет несколько задач на строки и unicode. Задача считается решённой, если все подзадачи решены. + +В задачах используются бенчмарки — тесты производительности, проверяющие, что ваше решение работает сильно не хуже, чем авторское. + +Сравнение с авторским решением происходит только в CI: локально бенчмарк не может "не пройти". + +Одной из сравниваемых статистик является количество аллокаций памяти. +Для поиска лишних аллокаций используйте [`pprof`](../docs/allocation_profiling.md). diff --git a/varfmt/README.md b/varfmt/README.md index 9de3ea0..6ae27ad 100644 --- a/varfmt/README.md +++ b/varfmt/README.md @@ -33,6 +33,8 @@ BenchmarkSprintf/big-4 12006 108144 ns/op 16392 B/op PASS ``` +Для поиска лишних аллокаций используйте [`pprof`](../docs/allocation_profiling.md). + ### Примеры Как запустить все тесты и бенчмарки: