3.6 KiB
3.6 KiB
Поиск лишних аллокаций
Для анализа аллокаций в задачах с бенчмарками удобно использовать встроенный в язык профайлер pprof
.
Сперва нужно запустить бенчмарк с профайлером
✗ go test -v -run=^$ -bench=BenchmarkSprintf -memprofile=mem.out ./varfmt/...
goos: linux
goarch: amd64
pkg: gitlab.com/manytask/itmo-go/private/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/manytask/itmo-go/private/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/manytask/itmo-go/private/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.