> Расскажите про опыт оптимизации (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Русклимат

Стек: Go

> Пример ответа

Короткий ответ

Оптимизация в Go - это системный процесс, а не набор трюков. Начинаю с профилирования (pprof), нахожу узкие места, затем применяю точечные изменения: аллокации, блокировки, копирование данных. Ключевой принцип - не оптимизировать вслепую, а измерять до и после. В production важнее предсказуемая latency и стабильное потребление памяти, чем микрооптимизация в ущерб читаемости.

Подробное объяснение

Мой опыт оптимизации в Go строится вокруг нескольких уровней:

Профилирование как отправная точка. Использую net/http/pprof в production (с ограничением доступа) и go test -bench для изолированных сценариев. CPU profile показывает горячие функции, heap profile - источники аллокаций, mutex profile - contention. Без этих данных любая оптимизация - гадание.

Типичные паттерны проблем в Go:

  • Избыточные аллокации из-за конкатенации строк, боксинга, замыканий
  • Копирование больших структур при передаче по значению
  • Неэффективная работа со слайсами (append в цикле без preallocation)
  • Сериализация (encoding/json) - частая горячая точка
  • Блокировки на горячем пути (sync.Mutex вместо RWMutex или атомиков)

Стратегия оптимизации:

  1. Сначала архитектура - убираю лишнюю работу (кэширование, батчинг, ленивые вычисления)
  2. Затем алгоритмы - сложность, структуры данных
  3. Потом микрооптимизации - аллокации, копирование, инлайнинг

Trade-off: каждая оптимизация увеличивает сложность кода. Поэтому всегда оцениваю выгоду: если функция занимает 2% CPU - не трогаю.

На практике

Реальный кейс: сервис обработки событий, где 70% CPU уходило на json.Unmarshal больших payload'ов. Решение - не менять формат, а добавить пул объектов (sync.Pool) и переиспользовать буферы. Плюс заменил map[string]interface{} на типизированные структуры. Итог: latency p99 упала с 80ms до 25ms, CPU - в 2 раза.

Второй кейс: горячая функция с fmt.Sprintf в цикле. Заменил на strconv.AppendInt с preallocated буфером - аллокации упали с 50k/s до нуля.

Третий кейс: contention на мьютексе в кэше. Перешёл на sharded locks (32 шарда) - throughput вырос в 4 раза без изменения логики.

Пример кода

GO
// Плохо: аллокации в цикле
func buildKey(parts []string) string {
var s string
for _, p := range parts {
s += p // каждая итерация - новая строка
}
return s
}
// Хорошо: preallocation
func buildKey(parts []string) string {
total := 0
for _, p := range parts {
total += len(p)
}
var b strings.Builder
b.Grow(total)
for _, p := range parts {
b.WriteString(p)
}
return b.String()
}
// Синхронизация: атомики вместо мьютекса для счётчика
type Counter struct {
v atomic.Int64
}
func (c *Counter) Inc() {
c.v.Add(1)
}
func (c *Counter) Value() int64 {
return c.v.Load()
}

Как отвечать на собеседовании

Структурируй ответ: сначала процесс (профилирование → гипотеза → изменение → измерение), затем конкретные примеры с цифрами. Покажи, что понимаешь trade-off между читаемостью и производительностью. Упомяни, что оптимизация - это итеративный процесс, а не одноразовое действие. Если спросят про конкретный инструмент - расскажи про pprof, benchstat, trace. Не уходи в абстракции - приводи реальные метрики.

Что проверяет интервьюер

  • Умеешь ли находить узкие места системно, а не наугад
  • Понимаешь ли внутренности Go: аллокации, GC, планировщик, sync.Pool
  • Можешь ли обосновать, почему выбрал именно эту оптимизацию
  • Осознаёшь ли цену оптимизации: сложность, поддерживаемость
  • Знаешь ли инструменты профилирования и умеешь интерпретировать их вывод

Типичные ошибки

  • Начинать с микрооптимизаций без профилирования - "оптимизация ради оптимизации"
  • Игнорировать GC pressure: снижение аллокаций часто важнее CPU
  • Менять логику ради скорости, ломая контракты
  • Забывать про бенчмарки до/после - нельзя оценить эффект
  • Оптимизировать холодные пути - тратить время на код, который выполняется редко
  • Использовать unsafe или ассемблер без крайней необходимости - это делает код неподдерживаемым

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью