Приходилось ли использовать профилировщики для поиска проблем в коде
Что проверяют
Оптимизируете ли вы по замеру или по догадке. Интервьюер хочет услышать связку: гипотеза, профиль, точечная правка, повторный бенчмарк. Плюс знание того, какой профиль что показывает.
Как отвечать
В Go всё нужное лежит в стандартной поставке:
- в бенчмарках:
go test -bench . -benchmem -cpuprofile cpu.out -memprofile mem.out, сравнение прогонов черезbenchstat; - в живом сервисе: импорт
net/http/pprofпод пустым идентификатором и отдельный слушатель на локальном адресе, дальшеgo tool pprof -http=:8080 ...; - внутри профиля:
topпо весу,listпо конкретной функции, граф вызовов и флейм-график.
Перечислите профили и их смысл: profile это процессорное время, heap по умолчанию показывает занятую память (inuse_space), а поток аллокаций виден в alloc_space; goroutine ловит утечку горутин; block и mutex показывают ожидание, но по умолчанию выключены и включаются через runtime.SetBlockProfileRate и runtime.SetMutexProfileFraction.
Рядом уместно назвать go tool trace для задержек и планировщика, GODEBUG=gctrace=1 по сборщику мусора и флаг -gcflags=-m для анализа убегания в кучу.
Где спотыкаются
Начинают с правки, а не с замера. Без профиля переписывается то, что занимает малую долю времени, и общая картина не меняется, зато код становится сложнее.
Путают профили: ищут причину роста памяти в процессорном профиле или смотрят только занятую память там, где проблема в частых короткоживущих аллокациях и давлении на сборщик. Про выключенные block и mutex тоже забывают и делают вывод, что ожидания на блокировках нет.
Подключают отладочный пакет и оставляют его на публичном порту. Импорт регистрирует ручки в мультиплексоре по умолчанию, и если основной сервер работает на нём же, профили уезжают наружу вместе с исходниками в листингах. Мелочь, которая выдаёт пересказ чужого примера: этот пакет импортируют только ради побочного эффекта, иначе код не соберётся.