Влияет ли размер объекта на размещение переменной в стеке или куче в Go
Что проверяют
Знаете ли вы, что место под переменную выбирает компилятор с помощью escape analysis, и понимаете ли, при чём тут размер. Следом просят показать, как проверить решение компилятора, и спрашивают, почему аллокации в куче вообще стоит считать.
Как отвечать
Короткий ответ: да, влияет, но это вторичный фактор. Главный вопрос в том, переживёт ли значение свою функцию:
- escape analysis: если ссылка на значение остаётся после выхода из функции, оно уходит в кучу. Типичные причины: возврат указателя на локальную переменную, запись в глобальную переменную или в поле структуры, которая живёт дольше, захват замыканием, которое переживёт вызов, отправка указателя в канал, упаковка в интерфейс, когда компилятор не видит, что с ним будет дальше;
- размер: даже не убегающее значение не поместят на стек, если оно слишком велико. В исходниках компилятора лимит для явно объявленных переменных порядка 10 МБ, а для неявных (
new(T),&T{},make) 64 КБ; - неизвестный размер:
make([]byte, n)сn, который не известен при компиляции, обычно тоже уходит в кучу. Слайс константной длины, который не убегает, компилятор спокойно размещает на стеке.
Проверяется это флагом go build -gcflags=-m: компилятор напишет moved to heap: x или escapes to heap. Цена кучи в том, что каждую аллокацию потом разбирает сборщик мусора, поэтому в горячем коде смотрят allocs/op в бенчмарках с -benchmem.
Стоит упомянуть, что стек у каждой горутины свой, стартует с нескольких килобайт и растёт копированием, так что большой объект на стеке делает этот рост дороже.
Где спотыкаются
Говорят, что слайсы, мапы и всё созданное через new всегда живут в куче. Решает не синтаксис, а анализ: new(T) без утечки ссылки легко окажется на стеке.
Пересказывают логику из C: «маленькое на стеке, большое в куче». Маленькая структура, чей адрес вернули из функции, уйдёт в кучу при любом размере.
Объясняют вред кучи фрагментацией. В Go основная цена это нагрузка на GC и время на сами аллокации, а не фрагментация.