perf, VTune и flame graphs: профилирование

Тема дорожной карты · Modern C++ Developer

Профилирование отвечает на единственный вопрос, который имеет значение при оптимизации: где именно программа тратит время. Интуиция здесь подводит даже опытных разработчиков, поэтому в C++-проектах измеряют, а не угадывают. Три инструмента закрывают почти все сценарии: perf из состава ядра Linux собирает сэмплы с минимальными накладными расходами, Intel VTune даёт микроархитектурный разбор (промахи кэша, неверные предсказания ветвлений, задержки конвейера), а flame graphs превращают тысячи стеков в одну картинку, по которой горячие пути видны за секунды.

Как это работает

perf использует аппаратные счётчики производительности (PMU) и механизм сэмплирования: несколько тысяч раз в секунду процессор прерывается, и ядро записывает текущий стек вызовов. Команда perf record -g ./app собирает такие сэмплы в файл, а perf report агрегирует их по функциям. Чем чаще функция попадает в сэмплы, тем больше времени она занимает. Для корректных стеков в релизной сборке нужны либо frame pointers (-fno-omit-frame-pointer), либо режим --call-graph dwarf, который разворачивает стек по отладочной информации.

VTune работает похожим образом, но добавляет анализ на уровне микроархитектуры. Режим Hotspots показывает горячие функции, а Microarchitecture Exploration раскладывает время по методологии Top-Down: сколько тактов ушло на фронтенд (декодирование инструкций), на бэкенд (ожидание памяти и исполнительных блоков), на неверные предсказания и на полезную работу. Именно этот разрез объясняет, почему функция медленная, а не только где она медленная.

Flame graph, придуманный Бренданом Греггом, строится из тех же стеков: скрипты stackcollapse-perf.pl и flamegraph.pl схлопывают одинаковые стеки и рисуют SVG, где ширина прямоугольника пропорциональна доле времени, а вертикаль соответствует глубине вызовов. Широкие плато наверху графика и есть кандидаты на оптимизацию.

Когда применять

Начинайте с perf, когда нужен быстрый ответ на production-подобной машине: инструмент есть в любом дистрибутиве, не требует перекомпиляции и вносит накладные расходы около одного процента. Flame graph подключайте сразу после сбора данных, если стек глубокий и текстовый отчёт perf report не читается. VTune уместен на втором шаге, когда горячая функция уже найдена, а причина неочевидна: например, цикл выглядит простым, но Top-Down показывает, что 70% тактов конвейер ждёт данные из памяти. Для HFT-систем, обработки видео и вычислительных ядер такой анализ обязателен, потому что там разница между версиями измеряется промахами кэша, а не строками кода.

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

Самая частая ошибка — профилировать debug-сборку. Без оптимизаций горячими становятся инлайнящиеся в релизе геттеры и проверки итераторов, и результат ничего не говорит о реальном коде. Собирайте с -O2 -g. Вторая ошибка — оптимизировать функцию с 3% времени, потому что она «выглядит плохо», игнорируя плато в 40%. Третья — измерять на ноутбуке с динамической частотой и не фиксировать governor, из-за чего прогоны отличаются на десятки процентов. Наконец, обрезанные стеки в flame graph («[unknown]») почти всегда означают отсутствие frame pointers в какой-то библиотеке; пересоберите зависимости или переключитесь на DWARF-развёртку.

Связанные понятия

Полезные ресурсы

🔤 Английские термины в этой теме

Слова из этой темы, которые русскоязычные часто произносят неверно. Кнопка 🔊 произносит голосом браузера.

Весь словарь терминов →