open atlas
↑ К треку
Производительность PERF · 02 · 01

Что делает путь горячим: симптом против причины

Широкий фрейм во flame graph показывает, где накапливается время, но не почему. Один и тот же leaf может скрывать пять разных узких мест — каждое требует своей правки.

PERF Junior ◷ 12 min
Уровень
ОсновыJuniorMiddleSenior
Уже знаешь этот юнит? Пройди быструю проверку за минуту →

Профиль готов. Один фрейм во flame graph широкий. Двое инженеров хотят сменить шаблонизатор. Третий спрашивает: «Широкий от чего? CPU-работа, аллокации, lock contention или syscall?» Только один из четырёх вариантов имеет «сменить шаблонизатор» как правильный fix.

Что такое hot path

Через десять минут ты будешь знать, как отличить пять очень разных проблем, одинаково выглядящих как «широкий фрейм» — и почему неверный диагноз тратит больше времени, чем отказ от оптимизации вовсе.

Hot path — это цепочка вызовов, в которой программа проводит большую часть времени. Профиль показывает её как стек широких фреймов, поднимающихся от leaf’а к top-level entry. Leaf называет функцию; вопрос — почему эта функция дорогая.

Современное железо превращает ту же «1 секунду CPU» в очень разные проблемы в зависимости от того, что CPU реально делал: исполнял инструкции, ждал памяти, ждал лока, ждал возврата syscall. Диагноз решает, какое семейство правок применимо.

Применение неверной правки к верному hotspot’у — вторая по частоте трата в performance-работе, после оптимизации не того hotspot’а вообще (разобрана в unit’е profile-first).

Метафора приёмной

Приёмная у врача переполнена. Это говорит, что в приёмной много людей — не говорит, почему. Пациенты ждут врача, лабораторию, бумаги, парковку? У каждого варианта своя правка: больше врачей, более быстрая лаборатория, меньше форм, больше мест для парковки.

Широкий фрейм во flame graph — то же самое: приёмная полная; спроси, чего люди ждут внутри.

Широкий фрейм показываетЧто это реально означаетКуда смотреть дальше
Высокий self-time в пользовательской функцииФункция делает настоящую CPU-работуИзучи алгоритм или data layout
Широкие GC-фреймы рядом с leaf’омCaller много аллоцируетПереключись на allocation profile
Широкий в wall-clock, узкий в CPUФункция ждёт — лок или syscallСними off-CPU или mutex profile
Фрейм интерпретатора там, где должен быть JITJIT деоптимизировался — откат к baselineСтабилизируй формы объектов / типы

Bea и Sven: один фрейм, два прочтения

Антон · Браузер находит processOrder на 35% CPU и хочет переписать цикл. Дима · Origin-сервер смотрит внимательнее: большая часть этих 35% — в runtime.scanobject (GC), вызываемом изнутри цикла. Цикл много аллоцирует. Правка — sync.Pool, не новый алгоритм.

Flame graph показал симптом. Причина — на уровень глубже.

Сценарий: regex на каждый запрос

Search-эндпоинт показывает regex.test как широкий leaf. Двое инженеров хотят сменить regex-движок. Третий смотрит на parent: regex компилируется на каждом запросе, потому что паттерн строится из шаблонной строки. Правка — компилировать один раз на старте. Leaf указал на правильную область; баг был в паттерне caller’а, не в самом leaf’е.

Почему это работает

Leaf — это лампочка на dashboard’е: «здесь что-то не так». Правка может быть внутри функции (переписать алгоритм), в caller’е (не вызывать так часто), в callee (реальная цена уровнем ниже) или в окружающем контексте (меньше аллоцировать, реже брать лок, меньше syscall’ов). Сеньоры читают весь район, не только leaf.

Викторина

Flame graph показывает широкий leaf-фрейм. Что спросить ПЕРВЫМ?

Викторина

Почему «широкий фрейм = bottleneck» — неполное прочтение flame graph?

Расставь шаги по порядку

Расставь шаги сеньорной атаки на hot path по порядку:

  1. 1 Открой профиль и найди самый широкий leaf-фрейм по self-time
  2. 2 Прочти parent chain — leaf вызывается из одного пути или из многих?
  3. 3 Классифицируй работу: CPU-инструкции, аллокации, cache miss, lock wait, syscall или JIT deopt
  4. 4 Сформулируй одну гипотезу правки, соответствующей классификации
  5. 5 Применить ТОЛЬКО это изменение изолированно
  6. 6 Сними новый профиль под той же нагрузкой и сравни с baseline
  7. 7 Убедись, что и локальный hotspot сжался, И headline-метрика улучшилась
Закончи аналогию

Вставь пропуск: широкий фрейм во flame graph называет _______; причина может сидеть уровнем выше (в caller'е), уровнем ниже (в callee) или в том, что функция реально делает.

Вспомните перед уходом
  1. 01
    В одном абзаце: почему назвать горячую функцию недостаточно — что ещё нужно прочесть из профиля, прежде чем её чинить?
  2. 02
    Приведи два конкретных примера, когда правка находится в caller'е, а не в широком leaf'е самом по себе.
Итог

Hot path — это цепочка вызовов, где программа проводит большую часть времени. Широкий leaf во flame graph называет функцию, но причина может быть в caller’е (слишком частые вызовы), в callee (реальная цена уровнем ниже) или в том, что функция делает (CPU-работа vs аллокации vs ожидание). Диагностический вопрос — какая из пяти форм этот hotspot — должен предшествовать выбору правки. Следующие уроки разбирают каждую из пяти форм и соответствующие семейства правок. Теперь, когда встретишь широкий фрейм, твой первый шаг — вопрос, а не переписывание.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 5 завершено
Связанные уроки
встречается в162

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

Примени это

Примени этот урок в реальном проекте.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.