1. pprof. Введение
Введение в профилирование и анатомия сэмплирования
«Можно увидеть очень многое, если просто внимательно смотреть».
— Йоги Берра«Диагностика без измерений — это гадание на кофейной гуще. Измерения без профилирования — это слепота».
— Инженерный афоризм Bell Labs
Представьте, что врач пытается диагностировать сложнейшее заболевание, имея на руках лишь один-единственный прибор — наручные часы. Он замеряет пульс пациента: 90 ударов в минуту. Слишком быстро? Возможно. Но что именно вызвало тахикардию — пробежка по лестнице, кофеин, волнение или порок сердца? По одним часам определить это невозможно. Требуется электрокардиограмма, рентген или магнитно-резонансный томограф (МРТ).
В разработке высоконагруженных бэкендов секундомером служат бенчмарки. В подразделе «Benchmarking» мы научились филигранно измерять время: писать надежные тесты (2. Benchmarking в Go), стабилизировать разброс показателей (6. Стабилизация результатов), снимать профили прямо во время тестов (7. Профилирование внутри benchmark) и математически сравнивать версии через benchstat (8. Сравнение версий кода). Но бенчмарк выдает лишь сухие числа ns/op. Он констатирует: «стало медленнее на 40%». Но почему стало медленнее? Какие строки кода жгут процессор? Где память утекает в кучу? На каких каналах или мьютексах засыпают горутины?
Главным диагностическим томографом в экосистеме Go является pprof — встроенный непосредственно в рантайм мощнейший фреймворк профилирования. Он позволяет заглянуть в самые сокровенные глубины исполняемого процесса без остановки сервиса и без использования тяжелых внешних отладчиков. В этой вводной лекции мы разберем архитектуру pprof, поймем, как операционная система Linux доставляет сигналы профилирования, какие бывают типы профилей и как правильно подготовить сервис к хирургически точной диагностике.
Что такое pprof и зачем он нужен
Исторически инструмент pprof родился внутри Google как часть библиотеки gperftools (Google Performance Tools) для анализа программ на C++. При создании Go инженеры Роб Пайк и Кен Томпсон заложили профилировщик прямо в ДНК языка: подсистема сбора метрик интегрирована непосредственно в рантайм Go (runtime/pprof).
pprof отвечает на ключевые вопросы оптимизации:
- CPU: В каких функциях и на каких конкретно инструкциях процессор проводит львиную долю тактов?
- Память (Heap): Кто выделяет гигабайты объектов в куче и провоцирует панические срабатывания Garbage Collector?
- Блокировки (Block/Mutex): Где горутины теряют время в очередях к мьютексам и системным вызовам?
- Горутины (Goroutines): Сколько горутин живо прямо сейчас и почему тысячи из них зависли в состоянии вечного ожидания?
Эта лекция открывает фундаментальный подраздел «03. CPU profiling». Здесь мы исследуем общую архитектуру pprof и механику сэмплирования, а в последующих статьях досконально изучим прикладные техники: 2. CPU profiling в Go, чтение огненных графиков 3. Flamegraph, анализ горячих точек 4. Top functions анализ, влияние инлайнинга 5. Inline и влияние на performance, предсказание переходов 6. Branch prediction и код, векторизацию 7. SIMD и Go и дружественность к кэшу процессора 8. Cache friendliness.
Архитектура pprof: сэмплирование и инструментирование
Фреймворк pprof сочетает в себе две принципиально разные парадигмы наблюдения:
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph TargetApp["Работающее Go-приложение (Runtime)"]
RT_M["Потоки ОС (M) и горутины (G)"]
RT_Alloc["Аллокатор памяти (mcache / mcentral)"]
RT_Sync["Примитивы синхронизации (sync.Mutex, каналы)"]
end
subgraph SamplingEngine["1. Механизм сэмплирования (CPU)"]
Timer["Ядро Linux: setitimer(ITIMER_PROF)"]:::system -->|"Сигнал SIGPROF 100 Гц"| SigHandler["Обработчик sigprof в рантайме"]
SigHandler -->|"Срез регистров PC, SP, BP"| StackTrace["Снятие стека без остановки мира"]
end
subgraph InstrumentationEngine["2. Механизм инструментирования (Event Tracing)"]
RT_Alloc -->|"Каждые 512 КБ (MemProfileRate)"| HeapHook["Хук аллокатора runtime.mallocgc"]
RT_Sync -->|"Блокировки > BlockProfileRate"| SyncHook["Хуки семафоров и мьютексов"]
end
TargetApp --> SamplingEngine
TargetApp --> InstrumentationEngine
StackTrace --> HashAgg["Хэш-таблица агрегации стеков вызовов"]
HeapHook --> ProfileProto["Генератор формата profile.proto (Gzip Protobuf)"]
SyncHook --> ProfileProto
HashAgg --> ProfileProto
ProfileProto --> Analyzer["go tool pprof<br>(Web UI, Flamegraph, CLI, Graphviz)"]
1. Сэмплирование (Sampling) — для CPU
Если бы рантайм перехватывал и замерял длительность абсолютно каждого вызова функции, программа замедлилась бы в 10–50 раз (так называемый трассировочный оверхед). Поэтому для CPU используется сэмплирующий подход:
- Рантайм не следит за каждой функцией непрерывно.
- Вместо этого через равные промежутки времени (по умолчанию 100 раз в секунду, 100 Гц) операционная система принудительно «фотографирует» текущее состояние процессора.
- По тысячам моментальных снимков строится статистически достоверная картина: если функция находилась под прицелом в 40% снимков, значит, она потребила около 40% процессорного времени.
2. Инструментирование (Instrumentation) — для памяти, блокировок и горутин
Для остальных ресурсов дискретное сэмплирование неприменимо:
- Куча (Heap): Рантайм Go внедряет точки учета прямо в аллокатор
runtime.mallocgc. Учет ведется по псевдослучайному экспоненциальному закону (в среднем 1 сэмпл на каждые 512 КБ выделенной памяти), что обеспечивает ничтожный оверхед (<1%). - Блокировки (Block / Mutex): Точки замера встроены в вызовы
sync.Mutex.Lock, каналы и планировщик. Рантайм фиксирует точную длительность ожидания разблокировки. - Горутины: Мгновенный обход глобального списка
allgsна момент запроса.
Виды профилей в pprof
Пакет стандартной библиотеки runtime/pprof и его веб-обвязка net/http/pprof предоставляют исчерпывающий спектр профилей. Каждый из них отвечает на строго определенный вопрос:
| Профиль | Диагностический вопрос | Механизм сбора | Ключевая статья в энциклопедии |
|---|---|---|---|
| CPU | На какие инструкции и функции процессор тратит такты? | Сэмплирование (SIGPROF 100 Гц) | 2. CPU profiling в Go |
Heap (inuse_space) |
Сколько оперативной памяти реально удерживается в куче прямо сейчас? | Инструментирование аллокатора | 5. pprof memory profile |
Heap (alloc_space) |
Где суммарно выделялась память за все время жизни (нагрузка на GC)? | Накопительный счетчик аллокаций | 4. Allocation profiling |
| Goroutine | Какие горутины активны, сколько их и где они заблокированы? | Снимок планировщика рантайма | 4. goroutine dump |
| Block | Сколько времени горутины провели во сне на каналах, мьютексах и syscall? | Трассировка времени ожидания | 5. block profile |
| Mutex | На каких именно мьютексах возникает жесткая конкуренция (contention)? | Трассировка столкновения локов | 6. mutex profile |
| Threadcreate | В каких участках кода создаются новые системные потоки ОС (M)? |
Инструментирование clone/pthread |
Раздел «Runtime и инструменты» |
Как работает сэмплирующий CPU-профайлер
Механика процессорного профилирования в Go — выдающийся образец системной инженерии. Она опирается на возможности ядра Linux и низкоуровневые POSIX-сигналы.
sequenceDiagram
autonumber
participant OS as Ядро Linux (Kernel)
participant Timer as POSIX Timer (setitimer)
participant M as Системный поток M
participant RT as Сигнальный обработчик Go (sigprof)
participant Buf as Циклический буфер профиля
Note over OS,M: Приложение исполняет пользовательский код Go
Timer->>OS: Истек интервал 10 мс (100 Гц)
OS->>M: Доставка сигнала SIGPROF
Note over M: Прерывание текущего контекста процессора!
M->>RT: Переход в обработчик runtime.sigprof
RT->>RT: Считывание регистров PC, SP, LR/BP
RT->>RT: Раскрутка стека вызовов (Stack Unwinding)
RT->>Buf: Запись среза адресов в системный буфер
RT-->>M: Возврат из обработчика сигнала (sigreturn)
Note over M: Возобновление выполнения прерванного кода
loop Фоновая агрегация
RT->>Buf: Чтение сырых адресов, символизация через pclntab
RT->>RT: Увеличение счетчиков в хэш-таблице профиля
end
Пошаговый алгоритм работы:
- Инициализация:
При старте профилирования (вызовомpprof.StartCPUProfile(w)) рантайм настраивает системный интервальный таймер вызовомsetitimer(ITIMER_PROF)(в современных ядрах Linux черезtimer_create). Частота по умолчанию устанавливается в 100 Гц (runtime.SetCPUProfileRate(100)), то есть одно прерывание каждые 10 миллисекунд. - Генерация сигнала SIGPROF:
Ядро Linux ведет независимый учет процессорного времени, потраченного процессом как в пространстве пользователя (User Mode), так и в ядре от имени процесса (System Mode). Каждые 10 мс ядро отправляет процессу сигналSIGPROF. - Перехват и регистрация:
Сигнал прерывает поток ОС (M). Управление передается низкоуровневому обработчикуruntime.sighandler/sigprof. Обработчик извлекает значения аппаратных регистров:PC(Program Counter) — адрес текущей выполняемой машинной инструкции.SP(Stack Pointer) — вершина текущего стека.BP/LR(Base Pointer / Link Register) — указатель кадра.
- Быстрая раскрутка стека (Stack Unwinding):
Обработчик быстро «пробегает» по кадрам стека прерванной горутины, не выделяя памяти в куче (любая аллокация внутри обработчика сигнала привела бы к взаимной блокировке deadlock!). Цепочка адресов инструкций записывается в предварительно выделенный кольцевой буфер. - Символизация и агрегация:
Специальная системная горутина профилировщика читает буфер, разрешает физические адреса в имена пакетов, функций и номера строк с помощью встроенной таблицыpclntab(PC-Line Table) и складывает результаты в итоговую хэш-таблицу. - Финализация:
При вызовеpprof.StopCPUProfile()таймер отключается, а накопленная хэш-таблица упаковывается в сжатый поток Gzip Protobuf и сохраняется в предоставленныйio.Writer.
Частота 100 Гц выбрана инженерами Bell Labs и Google как идеальный компромисс: она обеспечивает погрешность менее 1–2% при типичном времени снятия профиля в 30 секунд, создавая накладные расходы не более 1–3% CPU. При необходимости частоту можно изменить через runtime.SetCPUProfileRate(hz), но значения выше 1000 Гц могут заметно замедлить программу.
Погрешность сэмплирующего профайлера
Сэмплирование по определению является статистическим методом приближения. Понимание его ограничений отделяет Junior-разработчика от опытного инженера:
- Статистическая репрезентативность (Объем выборки):
Если вы снимете CPU-профиль длительностью всего 1 секунду, профилировщик успеет собрать лишь около 100 сэмплов. В такую выборку легко может попасть случайная фаза фонового сканирования GC или вызовruntime.memmove, создав ложную иллюзию катастрофы.
Правило: Достоверный профиль снимается не менее 10–30 секунд (от 1 000 до 3 000 сэмплов). - Систематическая ошибка (Зоны слепоты):
SIGPROFне фиксирует время, проведенное потоком в блокирующих системных вызовах ядра (чтение из сокета, запись на диск вread/write), если поток находится в состоянии сна. Если сервис «тормозит», ожидая ответа базы данных, CPU-профиль покажет почти 100% idle. Для анализа таких задержек предназначен Execution Tracer или блокировочный профиль. - Смещение выжившего (Survivorship Bias):
Сверхбыстрые функции, исполняющиеся за 2–5 наносекунд (например, простые геттеры или побитовые сдвиги), могут вообще не попасть ни в один из 100 сэмплов в секунду. Но это не ошибка — если функция работает наносекунды, она и не может быть причиной узкого места процессора! - Слияние путей вызовов (Stack Merging):
При глубокой рекурсии или полиморфных вызовах интерфейсов хэш-таблица агрегации может объединять разные логические ветви в один физический узел графа.
Способы получения профиля
В Go существует три канонических способа снятия профилей:
flowchart LR
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
subgraph Method1["1. net/http/pprof"]
M1["Веб-сервисы и демоны<br>HTTP эндпоинты /debug/pprof/"]:::network
end
subgraph Method2["2. runtime/pprof"]
M2["CLI утилиты и скрипты<br>Прямой вызов StartCPUProfile"]:::process
end
subgraph Method3["3. go test -bench"]
M3["Тестовые стенды и CI<br>Флаги -cpuprofile, -memprofile"]:::process
end
1. HTTP-эндпоинт net/http/pprof
Стандартный, общепринятый способ для микросервисов и фоновых демонов. Достаточно импортировать анонимный пакет:
package main
import (
"log"
"net/http"
_ "net/http/pprof" // Регистрирует обработчики на http.DefaultServeMux
)
func main() {
// Рекомендуется запускать pprof на отдельном внутреннем порту!
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// Основная бизнес-логика сервиса...
select {}
}
Анонимный импорт _ "net/http/pprof" автоматически монтирует следующие маршруты:
http://localhost:6060/debug/pprof/— веб-индекс всех доступных профилей.http://localhost:6060/debug/pprof/profile?seconds=30— запуск сбора CPU-профиля на 30 секунд (дефолт 30 с).http://localhost:6060/debug/pprof/heap— моментальный снимок памяти кучи.http://localhost:6060/debug/pprof/goroutine?debug=1— текстовый дамп всех горутин со стеками.http://localhost:6060/debug/pprof/block— накопительный профиль блокировок.http://localhost:6060/debug/pprof/mutex— профиль конкуренции за мьютексы.
Скачивание профиля из терминала:
# Снять 10-секундный CPU-профиль с работающего сервиса
curl -o cpu.prof "http://localhost:6060/debug/pprof/profile?seconds=10"
2. Прямой вызов runtime/pprof
Идеально подходит для консольных CLI-утилит, пакетных обработчиков данных или миграторов БД, где нет HTTP-сервера:
package main
import (
"os"
"runtime/pprof"
)
func main() {
f, err := os.Create("cpu.prof")
if err != nil {
panic(err)
}
defer f.Close()
// Включаем сбор сигналов SIGPROF
if err := pprof.StartCPUProfile(f); err != nil {
panic(err)
}
defer pprof.StopCPUProfile() // Гарантирует сброс буферов на диск при выходе
// Выполняем тяжелые вычисления...
}
3. Через тестовый фреймворк go test -bench
Как мы подробно изучили в 7. Профилирование внутри benchmark, флаги -cpuprofile, -memprofile, -blockprofile и -mutexprofile позволяют снять профиль изолированной функции на финальном прогоне бенчмарка:
go test -bench=BenchmarkProcess -cpuprofile=cpu.prof
Анализ профиля: go tool pprof
Снятый файл профиля (например, cpu.prof) представляет собой бинарный protobuf-документ. Для его исследования используется штатная утилита Go-инструментария: go tool pprof.
1. Интерактивный консольный режим (CLI)
go tool pprof cpu.prof
При входе открывается интерактивный шелл:
top: Показывает функции с наивысшим собственным потреблением CPU (flat).top -cum: Сортировка по кумулятивному времени (cum) с учетом всех дочерних вызовов.list functionName(илиlist <FunctionName>): Самая мощная команда CLI! Выводит исходный код функции построчно с точным указанием времени на каждой строке.web: Генерирует SVG-диаграмму графа вызовов и открывает ее в системном браузере (требует установленного пакета Graphviz).weblist functionName(илиweblist <FunctionName>): Открывает HTML-страницу с сопоставлением исходного кода и ассемблерных инструкций.pdf: Экспортирует граф вызовов в PDF-документ для отчетов.
2. Веб-интерфейс с Flamegraph
Современный стандарт анализа — запуск встроенного HTTP-сервера визуализации:
go tool pprof -http=:8080 cpu.prof
Утилита запустит локальный веб-сервер и откроет браузер на порту 8080, предоставляя:
- Flamegraph (3. Flamegraph): Интерактивная огненная диаграмма, где ширина прямоугольника строго пропорциональна времени выполнения функции.
- Graph (Граф вызовов): Направленный граф с цветовой индикацией тяжелых путей.
- Top (Табличный вид): Сортируемая таблица функций.
- Source: Построчный просмотр исходников с тепловой подсветкой.
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
RawProf["cpu.prof (Protobuf)"]:::system --> Tool["go tool pprof"]
Tool --> InteractiveCLI["Интерактивный CLI<br>(top, top -cum, list Foo)"]
Tool --> WebUI["Веб-интерфейс (:8080)<br>(Flamegraph, Call Graph, Source)"]
Пример сессии
В терминальной сессии команда top выводит структурированную таблицу распределения времени:
(pprof) top
Showing nodes accounting for 1.80s, 90% of 2.00s total
Dropped 15 nodes (cum <= 0.01s)
flat flat% sum% cum cum%
0.50s 25.00% 25.00% 0.80s 40.00% runtime.mallocgc
0.30s 15.00% 40.00% 0.30s 15.00% runtime.memmove
0.20s 10.00% 50.00% 0.20s 10.00% encoding/json.unmarshalString
...
flat(Собственное время): Время, проведенное процессором непосредственно внутри машинных инструкций данной функции (за вычетом времени выполнения дочерних вызовов).cum(Кумулятивное время): Совокупное время, проведенное в данной функции и всех вызванных ею подфункциях вниз по дереву стека.
Практический вывод:
Если у функции flat равен 0.05s, а cum равен 1.50s — сама функция является легким диспетчером, делегирующим работу потомкам.
Если же у функции flat равен 1.20s и cum равен 1.20s — это тяжелый вычислительный узел («листовая функция»), оптимизация алгоритма которой принесет максимальный дивиденд.
Mechanical Sympathy: влияние профилирования на производительность
Профилирование не дается даром. С точки зрения физики процессора и ядра ОС:
- Прерывание конвейера CPU:
Каждый сигналSIGPROFзаставляет ядро сохранить контекст пользовательского потока, сбросить конвейер инструкций и выполнить переход в обработчик сигналов. Это стоит сотни процессорных тактов и локально загрязняет кэш инструкций L1I. - Влияние на кэши данных (Cache Pollution):
Запись стека в кольцевой буфер профилировщика обращается к системным структурам памяти, вытесняя пользовательские данные из кэша L1D. - Хуки памяти и сборщик мусора:
Снятие моментального снимка кучи (heap profile) для точного учета живых объектов инициирует немедленный принудительный вызовruntime.GC(). Если в production-сервисе с кучей в 30 ГБ вызвать профиль heap под пиковым трафиком, принудительный STW и concurrent sweep могут вызвать кратковременный всплеск задержек (Latency Spike) на 50–100 мс!
Связь профилей с разделами энциклопедии
Инструмент pprof связывает воедино всю архитектуру нашей базы знаний:
flowchart TD
classDef process fill:#1e293b,stroke:#38bdf8,stroke-width:1px,color:#f8fafc
classDef success fill:#064e3b,stroke:#34d399,stroke-width:1px,color:#f8fafc
classDef error fill:#7f1d1d,stroke:#f87171,stroke-width:1px,color:#f8fafc
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:1px,color:#f8fafc
classDef entry fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef aux fill:#334155,stroke:#64748b,stroke-width:1px,color:#f8fafc
classDef system fill:#312e81,stroke:#a78bfa,stroke-width:1px,color:#f8fafc
classDef data fill:#132d29,stroke:#2dd4bf,stroke-width:1px,color:#f8fafc
classDef network fill:#881337,stroke:#fb7185,stroke-width:1px,color:#f8fafc
classDef accent fill:#1e1b4b,stroke:#818cf8,stroke-width:1px,color:#f8fafc
PProf["Экосистема pprof"]:::process
PProf --> CPU["CPU Profiling"]
CPU --> L2["[[2. CPU profiling в Go]]"]
CPU --> L3["[[3. Flamegraph]]"]
CPU --> L4["[[4. Top functions анализ]]"]
CPU --> L5["[[5. Inline и влияние на performance]]"]
CPU --> L6["[[6. Branch prediction и код]]"]
CPU --> L7["[[7. SIMD и Go]]"]
CPU --> L8["[[8. Cache friendliness]]"]
PProf --> Mem["Memory Profiling"]
Mem --> M2["[[2. Heap vs stack]]"]
Mem --> M3["[[3. Escape analysis]]"]
Mem --> M4["[[4. Allocation profiling]]"]
Mem --> M5["[[5. pprof memory profile]]"]
Mem --> M6["[[6. Утечки памяти]]"]
Mem --> M7["[[7. Fragmentation]]"]
PProf --> Sync["Concurrency & Lock Profiling"]
Sync --> S5["[[5. block profile]]"]
Sync --> S6["[[6. mutex profile]]"]
Sync --> S7["[[7. Contention и lock profiling]]"]
Sync --> S8["[[8. False sharing]]"]
Итог
pprof— встроенный в рантайм Go томограф: Он переводит инженерию производительности из плоскости слепых догадок в доказательную медицину.- Гибридная архитектура: Сэмплирование CPU по сигналам
SIGPROFс частотой 100 Гц дает минимальный оверхед (1–3%), а точечное инструментирование памяти и блокировок фиксирует точные события распределения ресурсов. - Ортогональность профилей: CPU — для горячих вычислений, Heap — для давления на GC, Block и Mutex — для Off-CPU задержек и очередей синхронизации.
- Статистическая надежность: Снимайте профили не менее 10–30 секунд, чтобы исключить искажения от малых выборок.
- Безопасность прежде всего: Никогда не выставляйте эндпоинты
net/http/pprofна публичный интерфейс0.0.0.0.
В следующей лекции 2. CPU profiling в Go мы перейдем от теории к детальной практике: пошагово разберем снятие процессорных профилей, научимся фильтровать шум стандартной библиотеки и находить скрытые бутылочные горлышки в алгоритмах.