Ответ
Escape Analysis (анализ утечек) — это процесс, в ходе которого компилятор Go определяет, где должна быть выделена память для переменной: в стеке (stack) или в куче (heap).
- Стек (Stack): Быстрая память, выделяется для каждой горутины. Память очищается автоматически при выходе из функции. Доступ к стеку не требует участия сборщика мусора (GC).
- Куча (Heap): Более медленная, общая для всей программы память. Объекты в куче управляются сборщиком мусора, что создает дополнительную нагрузку.
Переменная «утекает» (escapes) в кучу, если компилятор не может доказать, что её время жизни ограничено текущим стековым фреймом (вызовом функции). Это происходит в следующих случаях:
-
Возврат указателя на локальную переменную: Указатель переживает функцию, которая его создала.
func createUser() *User { // Возвращаем указатель u := User{Name: "Alice"} // 'u' будет создана в куче return &u }
-
Сохранение указателя в глобальной переменной или другой структуре в куче.
-
Размер переменной неизвестен на этапе компиляции: Например, при создании среза, размер которого зависит от входных данных.
-
Отправка указателя в канал: Жизненный цикл переменной становится непредсказуемым для компилятора.
-
Вызов метода на интерфейсе: Компилятор не знает конкретный тип и не может применить оптимизации, поэтому данные часто перемещаются в кучу.
Зачем это знать?
Размещение в куче приводит к дополнительной работе для сборщика мусора и может снизить производительность. Оптимизация кода для уменьшения количества «утечек» — важная часть работы над высокопроизводительными приложениями.
Как обнаружить?
Используйте флаг -gcflags="-m"
при сборке:
# Команда для анализа
go build -gcflags="-m" ./...
# Пример вывода
./main.go:6:9: &u escapes to heap // Компилятор сообщает, что &u утекает в кучу