Skip to content
1 / 15

Память процесса Go: стек, куча и почему RSS больше, чем кажется

Память процесса Go состоит из нескольких частей, и мониторинг обычно показывает не ту, которую ожидают. Стеки горутин начинаются с нескольких килобайт и растут по надобности; сотня тысяч горутин — это уже сотни мегабайт. Куча содержит всё, что не поместилось на стек по решению escape-анализа. Отдельно живут служебные структуры рантайма: метаданные сборщика, таблицы типов, кеши распределителя. Важное расхождение: HeapAlloc из runtime.MemStats — это живые объекты кучи, а RSS, который видит операционная система и мониторинг контейнера, включает ещё и освобождённую, но не возвращённую системе память, стеки, служебные структуры и код. Поэтому RSS почти всегда заметно больше HeapAlloc, и это нормально, а не утечка. Возвращает память Go не сразу: сборщик отдаёт её постепенно фоновым процессом, а с GOMEMLIMIT — активнее. Принудить можно debug.FreeOSMemory, но в проде это почти всегда лишнее.

Память процесса Go: стек, куча и почему RSS больше, чем кажется | JScriptiser