awesome-everything EN
↑ Обратно к восхождению

Производительность

Пять форм hotspot''''а: CPU, аллокации, кэш, лок, syscall

Суть У каждой из пяти категорий hotspot''''а есть характерная сигнатура в профиле и соответствующее семейство правок. Выбрать неверное семейство — значит потратить усилия впустую.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на middle-высоте — в небе
◷ 18 min

Два широких leaf’а во flame graph на первый взгляд выглядят одинаково. Один требует лучшего алгоритма. Второй требует переиспользования буферов. Применить лучший алгоритм к allocation-bound-пути — значит получить 1,05x вместо предсказанных 3x. Два часа работы ради пяти процентов. Категория определяет toolbox.

Пять категорий

Широкий leaf подходит под одну из пяти категорий. Прочтение второго слоя профиля — не только «какая функция», но «что функция делает» — даёт классификацию.

1. CPU-bound алгоритмический

Функция исполняет много инструкций. CPU исполняет алгоритм.

Сигнатура: большой self-time, узкие children, высокий instructions-per-second, IPC в диапазоне 2–4. В CPU flame graph leaf занимает настоящую ширину без GC или kernel-фреймов рядом.

Семейство правок: лучший алгоритм, векторизация (SIMD), inline-pragma, специализация hot-path’а для частого случая.

2. Allocation-bound

Функция (или её caller) так много аллоцирует, что сборщик мусора доминирует над wall-time.

Сигнатура: runtime.scanobject, gc, mallocgc или malloc появляются широкими рядом с горячим leaf’ом. CPU-профиль винит GC-machinery, не application-логику. Переключись на allocation-профиль, чтобы найти аллокатор на стороне приложения.

Семейство правок: пулинг объектов, переиспользование буферов (sync.Pool), in-place мутация, struct-of-arrays, предварительное выделение контейнеров нужного размера.

3. Cache-bound

Функция трогает память по паттерну, который аппаратный prefetcher не может предсказать. CPU стопорится, ожидая данные из RAM вместо L1/L2.

Сигнатура: низкий IPC (<1), высокий cache-miss rate (15%+), низкий instructions-per-second несмотря на широкий CPU-фрейм. Аппаратные счётчики подтверждают тип stall (L3 miss, DRAM stall).

Семейство правок: смена data-layout’а (contiguous arrays вместо pointer-chased linked lists, struct-of-arrays вместо array-of-structs), смена порядка итерации для улучшения spatial locality, prefetch-подсказки.

4. Lock-bound

Функция тратит время в ожидании mutex’а или канала.

Сигнатура: широкая в mutex/block/off-CPU профиле, узкая в CPU-профиле. Функция off-CPU, не работает. Wall-clock time высокий; CPU time низкий.

Семейство правок: lock-free структуры данных, более гранулярные локи, шардированное состояние, read-write локи для read-heavy-путей, eventual consistency для устранения shared state.

5. Syscall-bound

Функция тратит время в ядре — чтение, запись, сетевой I/O или ожидание на futex.

Сигнатура: kernel-фреймы (read, write, recv, futex) видны во flame graph с поддержкой kernel-символов. Доминирует off-CPU время. Может проявляться как частые узкие kernel-entry вместо одного широкого leaf’а.

Семейство правок: батчинг syscall’ов (один writev вместо десяти write), большие I/O-буферы, io_uring для async kernel I/O, memory-mapped I/O, полное устранение syscall’а там, где данные могут оставаться в user space.

КатегорияСигнатура в профилеСемейство правок
CPU-boundВысокий self-time, IPC 2–4Лучший алгоритм, SIMD, специализация
Allocation-boundШирокие GC-фреймы (mallocgc, scanobject)Пулинг, переиспользование буферов, SoA
Cache-boundIPC <1, высокий cache-miss rateСмена data layout, contiguous arrays
Lock-boundШирокий off-CPU, узкий on-CPULock-free, шардирование, мелкие локи
Syscall-boundKernel-фреймы во flame graphБатчинг syscall’ов, io_uring, буферы
Числа диагностики hot path'ов
Типовой IPC compute-bound кода
2–4 инстр./цикл
Типовой IPC memory-bound кода
0,3–0,8 инстр./цикл
Штраф L1 cache miss
~5 циклов
Штраф L3 cache miss → DRAM
~150–300 циклов
Штраф branch mispredict
~15–25 циклов
Цена одного deopt + recompile (V8)
~10–100 мкс
Round-trip syscall
~1–5 мкс
futex lock contention wakeup
~5–50 мкс

Классификация hotspot’а на практике

Классифицируй hotspot до выбора правки

1/3
Викторина

Функция показывает IPC 0,4 и cache-miss rate 15%. Какова категория и какое семейство правок она предполагает?

Викторина

После правки локальный hotspot сжался на 60%, но p99 сервиса не изменился. Что скорее всего это означает?

Вспомните перед уходом
  1. 01
    Разбери пять категорий hot path'ов с одним характерным признаком каждой в профиле и соответствующим семейством правок.
  2. 02
    Go API показывает runtime.mallocgc на 18% и runtime.scanobject на 14% в CPU-профиле. Какова категория и каков следующий диагностический шаг?
Итог

Пять категорий hotspot’ов — CPU, аллокации, кэш, лок, syscall — у каждой чёткая сигнатура в профиле: IPC и self-time для CPU-bound, GC-фреймы для allocation-bound, низкий IPC с высоким cache-miss для cache-bound, широкий off-CPU но узкий on-CPU для lock-bound, kernel-фреймы для syscall-bound. Диагноз занимает минуты (снять нужный вторичный профиль, прочитать IPC или miss-rate); семейство правок следует механически. Выбрать неверное семейство — значит потратить всю работу впустую. Следующий урок разбирает, как читать parent и child chains, чтобы локализовать правку на верном уровне дерева вызовов.

Связанные уроки
встречается в159
Продолжить восхождение ↑Чтение parent и child chains: где применять правку
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.