Краткая методика — шаги + что мерить + практические приёмы. 1) Определить симптом - Что плохо: задержки/хвостовые латенции, падение пропускной способности (RPS), рост памяти, утечки горутин. - Соберите базовые метрики: latency ( p50,p95,p99p50, p95, p99p50,p95,p99 ), RPS, error-rate, CPU %, RSS. 2) Воспроизведение под нагрузкой - Запустить стабильный нагрузочный сценарий (репродуцируемый). Фиксировать входной RPS/конфигурацию. Пример: нагрузка NNN потоков/clients. 3) Профилирование (порядок) - CPU-профайл: через net/http/pprof или runtime/pprof. Пример запроса профиля: /debug/pprof/profile?seconds=303030. - Анализ: go tool pprof, pprof web, speedscope, flamegraph. - Heap-профайл: /debug/pprof/heap — ищем рост аллокаций и горшок короткоживущих объектов. - Goroutine dump: /debug/pprof/goroutine?debug=222 — ищем блокировки/утечки. - Block-профайл и mutex-профайл: /debug/pprof/block, /debug/pprof/mutex — показывают ожидания на каналах, mutex/time spent waiting. - Trace: runtime/trace + go tool trace — видна планировка горутин, syscalls, остановки GC, сетевые syscalls, длительные блокировки. - OS-level: top/htop, pidstat, perf для syscalls, iostat, netstat. 4) Важные метрики (мониторинг) - Latency percentiles: p50,p95,p99p50, p95, p99p50,p95,p99. - Throughput: RPS (requests/s). - Error rate / success ratio. - CPU usage: total and per-core. - Goroutines: count и рост (runtime.NumGoroutine()). - HeapAlloc, HeapObjects, Mallocs/Frees (runtime.MemStats). - GC: pause duration distribution, GC count, GOGC-influence. - Block/mutex wait times (из профилей). - Thread count (OS threads), syscall time. - Channel metrics: len(ch), cap(ch) (снятие в экспортере) и время ожидания на send/recv (custom histogram). - Scheduler latency / syscalls waiting (из trace). 5) Анализ профилей — что искать - Горячие функции в CPU-профиле (самые затратные). - Функции с высоким allocation rate в heap snapshot. - Длительные блокировки/очереди по mutex/block profile — узкие места синхронизации. - Множество «stuck» горутин на одном стеке (например, все ждут на одном канале/мьютексе). - Частые GC из-за большого количества мелких аллокаций. 6) Типичные оптимизации (по типу проблемы) - CPU-bound: - Оптимизировать алгоритм (алгоритмическая сложность). - Уменьшить аллокации в hot path (избегать fmt.Sprintf, выделений срезов и т.п.). - Использовать sync.Pool для часто создаваемых объектов или буферов. - Профилировать и инлайнинг; компилятор. - Memory/GC pressure: - Переиспользовать буферы (bytes.Buffer, bufio) и объекты. - Уменьшить количество временных слайсов/строк. - Настроить GOGC (экспериментально), но лучше снижать аллокации. - Lock contention: - Шардинг данных вместо одного глобального мьютекса. - Использовать более мелкие блоки синхронизации, read-write locks (sync.RWMutex) там где уместно. - Перейти на атомики (sync/atomic) для простых счётчиков. - Анализировать mutex profile и убрать hot locks. - Goroutine/channel issues: - Избегать бесконтрольного форка горутин; использовать worker pool / bounded concurrency (семафор). - Для высокочастотных каналов — подобрать буферизацию (buffered channels) или batch-подход. - Избегать blocking send/recv в hot path: select с default, таймауты, backpressure. - Проверять и закрывать каналы корректно; использовать контекст для отмены. - I/O-bound: - Batch запросы, pipelining, уменьшить syscalls. - Использовать эффективные парсеры/буферы. - Параллелизм / GOMAXPROCS: - Тестировать разные значения GOMAXPROCS; обычно равен числу логical CPU. - Следить за scheduler latency и количеством OS threads. 7) Контрольные эксперименты и итерации - Внести одну оптимизацию, прогнать нагрузочный тест, сравнить метрики (latency p95/p99, RPS, CPU, GC). - Регресс-тесты: убедиться, что оптимизация не ухудшила другие показатели. - Автоматизировать сбор профилей и метрик при нагрузочных тестах. 8) Практические команды / инструменты (коротко) - Включить pprof: import _ "net/http/pprof". - CPU профайл: curl localhost:8080/debug/pprof/profile?seconds=303030 > cpu.pb; go tool pprof ./binary cpu.pb - Heap: curl /debug/pprof/heap > heap.pb - Trace: curl /debug/pprof/trace?seconds=555 > trace.out; go tool trace trace.out - Анализ: go tool pprof -http=":8081" cpu.pb - Дополнительно: speedscope, FlameGraph, go-torch. Короткий чеклист перед оптимизацией - Репroduce под нагрузкой. - Собрать CPU + block + mutex + goroutine + heap + trace. - Выявить: heavy funcs, contention, GC pressure, goroutine leaks. - Применить таргетные правки (меньше аллокаций, пул, шардирование, bounded concurrency, буферизация каналов). - Измерить и вернуться к шагу повторно. Если нужно, могу дать шаблон метрик Prometheus или пример профилирования для конкретного кейса.
1) Определить симптом
- Что плохо: задержки/хвостовые латенции, падение пропускной способности (RPS), рост памяти, утечки горутин.
- Соберите базовые метрики: latency ( p50,p95,p99p50, p95, p99p50,p95,p99 ), RPS, error-rate, CPU %, RSS.
2) Воспроизведение под нагрузкой
- Запустить стабильный нагрузочный сценарий (репродуцируемый). Фиксировать входной RPS/конфигурацию. Пример: нагрузка NNN потоков/clients.
3) Профилирование (порядок)
- CPU-профайл: через net/http/pprof или runtime/pprof. Пример запроса профиля: /debug/pprof/profile?seconds=303030.
- Анализ: go tool pprof, pprof web, speedscope, flamegraph.
- Heap-профайл: /debug/pprof/heap — ищем рост аллокаций и горшок короткоживущих объектов.
- Goroutine dump: /debug/pprof/goroutine?debug=222 — ищем блокировки/утечки.
- Block-профайл и mutex-профайл: /debug/pprof/block, /debug/pprof/mutex — показывают ожидания на каналах, mutex/time spent waiting.
- Trace: runtime/trace + go tool trace — видна планировка горутин, syscalls, остановки GC, сетевые syscalls, длительные блокировки.
- OS-level: top/htop, pidstat, perf для syscalls, iostat, netstat.
4) Важные метрики (мониторинг)
- Latency percentiles: p50,p95,p99p50, p95, p99p50,p95,p99.
- Throughput: RPS (requests/s).
- Error rate / success ratio.
- CPU usage: total and per-core.
- Goroutines: count и рост (runtime.NumGoroutine()).
- HeapAlloc, HeapObjects, Mallocs/Frees (runtime.MemStats).
- GC: pause duration distribution, GC count, GOGC-influence.
- Block/mutex wait times (из профилей).
- Thread count (OS threads), syscall time.
- Channel metrics: len(ch), cap(ch) (снятие в экспортере) и время ожидания на send/recv (custom histogram).
- Scheduler latency / syscalls waiting (из trace).
5) Анализ профилей — что искать
- Горячие функции в CPU-профиле (самые затратные).
- Функции с высоким allocation rate в heap snapshot.
- Длительные блокировки/очереди по mutex/block profile — узкие места синхронизации.
- Множество «stuck» горутин на одном стеке (например, все ждут на одном канале/мьютексе).
- Частые GC из-за большого количества мелких аллокаций.
6) Типичные оптимизации (по типу проблемы)
- CPU-bound:
- Оптимизировать алгоритм (алгоритмическая сложность).
- Уменьшить аллокации в hot path (избегать fmt.Sprintf, выделений срезов и т.п.).
- Использовать sync.Pool для часто создаваемых объектов или буферов.
- Профилировать и инлайнинг; компилятор.
- Memory/GC pressure:
- Переиспользовать буферы (bytes.Buffer, bufio) и объекты.
- Уменьшить количество временных слайсов/строк.
- Настроить GOGC (экспериментально), но лучше снижать аллокации.
- Lock contention:
- Шардинг данных вместо одного глобального мьютекса.
- Использовать более мелкие блоки синхронизации, read-write locks (sync.RWMutex) там где уместно.
- Перейти на атомики (sync/atomic) для простых счётчиков.
- Анализировать mutex profile и убрать hot locks.
- Goroutine/channel issues:
- Избегать бесконтрольного форка горутин; использовать worker pool / bounded concurrency (семафор).
- Для высокочастотных каналов — подобрать буферизацию (buffered channels) или batch-подход.
- Избегать blocking send/recv в hot path: select с default, таймауты, backpressure.
- Проверять и закрывать каналы корректно; использовать контекст для отмены.
- I/O-bound:
- Batch запросы, pipelining, уменьшить syscalls.
- Использовать эффективные парсеры/буферы.
- Параллелизм / GOMAXPROCS:
- Тестировать разные значения GOMAXPROCS; обычно равен числу логical CPU.
- Следить за scheduler latency и количеством OS threads.
7) Контрольные эксперименты и итерации
- Внести одну оптимизацию, прогнать нагрузочный тест, сравнить метрики (latency p95/p99, RPS, CPU, GC).
- Регресс-тесты: убедиться, что оптимизация не ухудшила другие показатели.
- Автоматизировать сбор профилей и метрик при нагрузочных тестах.
8) Практические команды / инструменты (коротко)
- Включить pprof: import _ "net/http/pprof".
- CPU профайл: curl localhost:8080/debug/pprof/profile?seconds=303030 > cpu.pb; go tool pprof ./binary cpu.pb
- Heap: curl /debug/pprof/heap > heap.pb
- Trace: curl /debug/pprof/trace?seconds=555 > trace.out; go tool trace trace.out
- Анализ: go tool pprof -http=":8081" cpu.pb
- Дополнительно: speedscope, FlameGraph, go-torch.
Короткий чеклист перед оптимизацией
- Репroduce под нагрузкой.
- Собрать CPU + block + mutex + goroutine + heap + trace.
- Выявить: heavy funcs, contention, GC pressure, goroutine leaks.
- Применить таргетные правки (меньше аллокаций, пул, шардирование, bounded concurrency, буферизация каналов).
- Измерить и вернуться к шагу повторно.
Если нужно, могу дать шаблон метрик Prometheus или пример профилирования для конкретного кейса.