Частые аллокации создают работу сборщику мусора. Снижать их нужно после профиля, потому что не каждая аллокация плоха: иногда она упрощает код и почти ничего не стоит.
Смотрим решения компилятора
go build -gcflags=-m ./...
Компилятор сообщает, какие значения уходят в кучу. Типичные причины:
- возвращается указатель на локальное значение;
- значение попадает в интерфейс;
- срез или замыкание живёт дольше функции;
- большой объект передаётся по значению.
Компилятор смотрит на время жизни значения. Указатель сам по себе не означает кучу, а escape не всегда требует оптимизации.
Escape analysis не враг сам по себе. Нужна причина в горячем пути, а не исправление всех строк вывода.
Лишние копии
append может выделить новый массив. Если ёмкость известна, её задают заранее:
result := make([]string, 0, len(items))
for _, item := range items {
result = append(result, item.Name)
}
strings.Builder уменьшает число временных строк при сборке. fmt.Sprintf удобен, но в горячем цикле может создавать лишние аллокации и отражения типов.
strings.Clone и bytes.Clone создают копию намеренно: она нужна, чтобы не держать большой исходный массив. Убирать такую копию без анализа нельзя.
Интерфейсы и значения
Передача большой структуры по значению копирует её. Указатель уменьшает копирование, но продлевает жизнь объекта. Поэтому оптимизация начинается с понимания владения, а не с замены всех значений указателями.
Передача значения в interface{} иногда приводит к выделению в куче. Здесь помогает сигнатура с конкретным типом или меньшее значение.
Pool
sync.Pool переиспользует буферы, но очищает их при возврате и не гарантирует хранение. Он полезен для частых одинаковых аллокаций после бенчмарка, а не как универсальное ускорение.
Проверка эффекта: allocs/op, B/op, доля GC в CPU и итоговая latency. Меньше аллокаций без улучшения latency - не всегда победа.
Коротко
- Сначала
benchmemи-gcflags=-m, затем изменения. - Ёмкость срезов и Builder убирают лишние выделения.
- Копия иногда нужна для освобождения большого массива.
- Пул используют только после доказанной выгоды.