Рост RSS не доказывает утечку. Рантайм берёт память у ОС и возвращает постепенно. Важна нижняя точка после сборки и то, что остаётся живым.
Пила после сборки
Здоровый сервис показывает пилу: память растёт до сборки и падает примерно к одному уровню. Утечка поднимает нижние точки со временем.
О сборке говорит пила, об утечке - рост нижних точек после GC. RSS при этом может оставаться высоким.
Первые графики:
go_goroutines- не растёт ли число горутин;go_memstats_heap_inuse_bytes- сколько живёт сейчас;go_memstats_next_gc_bytes- цель следующей сборки;process_resident_memory_bytes- весь процесс, включая вне Go-память.
Если горутины растут, начинаем с pprof/goroutine. Если куча растёт - с pprof/heap и разреза inuse_space.
GOGC и GOMEMLIMIT
GOGC задаёт отношение роста кучи, а не лимит. GOMEMLIMIT - мягкий предел, при приближении к которому GC работает чаще.
В контейнере GOMEMLIMIT обычно ставят на 80-90% лимита, оставляя место для cgo, стеков и памяти вне Go. Слишком низкий предел вызывает постоянные сборки и высокий CPU.
GOGC меняют после профиля: увеличение снижает число сборок ценой памяти, уменьшение - наоборот.
Утечка или задержка возврата
Память после GC может не вернуться ОС сразу. Это выглядит как высокая полка, но она не растёт бесконечно. Утечка растёт монотонно и меняет нижнюю точку.
Различают:
- живые объекты;
- стеки горутин;
- память cgo;
- ещё не возвращённые страницы ОС.
Поэтому сравнивают heap_inuse, stack_inuse, sys и resident.
Коротко
- Утечка видна по росту нижней точки после GC, не по одному графику RSS.
- Сначала горутины, затем heap, затем память вне Go.
GOMEMLIMITмягкий,GOGCотношение, а не предел.- Высокая полка после сборки не всегда утечка.