Когда очищается память массива под слайсом в Go
Что проверяют
Понимаете ли вы, что слайс это лишь заголовок из указателя, длины и ёмкости, а память принадлежит массиву под ним. Главный подвох: маленький подслайс держит живым весь большой массив. Следом обычно просят показать, как такую утечку найти и исправить.
Как отвечать
Правило простое: сборщик мусора освобождает массив, когда из живых данных до него нельзя дойти ни одним указателем. Указатель в середину массива держит его целиком, отрезать неиспользуемый хвост GC не умеет.
- подслайс:
small := big[10:20]не копирует данные. Пока живsmall, жив и весьbig, даже если в нём мегабайты. Типичный пример: прочитали файл черезos.ReadFileи сохранили в кэш короткий кусок; - копирование: чтобы отпустить исходник, скопируйте нужное через
slices.Clone(Go 1.21),bytes.Clone(Go 1.20) илиappend([]T(nil), s[a:b]...); s = s[:0]: длина обнулилась, массив остался. Это как раз способ переиспользовать буфер без новых аллокаций;- хвост за длиной: элементы между
lenиcapневидимы, но если там указатели, объекты по ним тоже не соберутся. Их обнуляют встроеннымclear(Go 1.21), аslices.Deleteс Go 1.22 делает это сам; - рост через
append: при нехватке ёмкости выделяется новый массив и данные копируются. Старый станет мусором, только если на него не ссылается никто другой; - стек: если массив не убегает из функции (escape analysis, смотреть через
go build -gcflags=-m), он лежит на стеке и исчезает при выходе без участия GC.
Сама сборка идёт не мгновенно, а в очередном цикле, темп которого задают GOGC (по умолчанию 100) и GOMEMLIMIT. Освобождённые страницы возвращаются операционной системе позже, так что RSS процесса падает с задержкой.
Где спотыкаются
Пишут big = nil и считают память освобождённой, забыв, что где-то остался подслайс на кусок этого массива.
Думают, что трёхиндексный срез s[a:b:b] отпускает лишнее. Он только ограничивает ёмкость, чтобы append не затёр чужие данные, массив остаётся прежним.
Ждут, что runtime.GC() или обнуление сразу уменьшат потребление памяти в мониторинге, и делают неверные выводы об утечке.