Типы профилировщиков
В LLVM уже есть инструмент, который добавляет в код инструментацию и позволяет выполнять инструментальное профилирование. В отличие от сэмплирования или статистического профилирования, оно очень точно и не пропускает ни одного вызова, но требует инструментировать код и потребляет больше ресурсов.
Если кратко, профилировщик с инструментированием добавляет в код новый код для отслеживания вызовов всех функций. Статистические профилировщики позволяют запускать код без каких-либо изменений, периодически создавая снимки, чтобы видеть состояние приложения. Поэтому учитываются только те функции, которые выполняются в момент создания снимка. perf — очень известный статистический профилировщик.
Профилирование ClickHouse с помощью интеграции XRay
В ClickHouse 25.12 XRay интегрирован так, чтобы можно было без проблем добавлять новые точки инструментирования в функции. Поэтому в любом официальном релизе эта возможность уже доступна и ее можно включать по мере необходимости, не влияя на общую производительность, когда она не включена. Идея в том, чтобы задействовать минимальное количество точек инструментирования и при этом получать ценную информацию.
Мы можем добавить новую точку инструментирования для профилирования с помощью оператора SYSTEM INSTRUMENT ADD
PROFILE.
Функции, которые нужно инструментировать, можно получить из
системной таблицы system.symbols. Допустим, мы
хотим профилировать функцию sleepForNanoseconds — это удобная функция, чтобы проверить, сколько времени
занимает ее выполнение.
SYSTEM INSTRUMENT ADD 'sleepForNanoseconds' PROFILEЗатем оставляем его работать на нужный нам период профилирования и останавливаем.
SYSTEM INSTRUMENT REMOVE ALLМы преобразуем данные, собранные в system.trace_log, в формат Chrome, чтобы визуализировать их в Perfetto. Обратите внимание на query_id, cpu_id и трассировку стека для каждой записи.

Профилирование нативного приложения с помощью XRay
Следующий раздел оставлен в качестве справочного материала, чтобы показать, как XRay работает на низком уровне и как его можно использовать из коробки для профилирования нативного приложения.
Добавьте инструментацию в код
Представьте себе следующий исходный код:
#include <chrono>
#include <cstdio>
#include <thread>
void one()
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
void two()
{
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
int main()
{
printf("Start\n");
for (int i = 0; i < 10; ++i)
{
one();
two();
}
printf("Finish\n");
}Чтобы включить инструментирование с помощью XRay, нужно добавить несколько флагов, например:
clang++ -o test test.cpp -fxray-instrument -fxray-instruction-threshold=1-fxray-instrumentнужен, чтобы инструментировать код.-fxray-instruction-threshold=1используется, чтобы инструментировать все функции, даже если они очень маленькие, как в нашем примере. По умолчанию инструментируются функции, содержащие не менее 200 инструкций.
Проверить, что код был инструментирован правильно, можно по появлению нового раздела в бинарном файле:
objdump -h -j xray_instr_map test
test: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
17 xray_instr_map 000005c0 000000000002f91c 000000000002f91c 0002f91c 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATAЗапустите процесс с корректными значениями переменных окружения, чтобы собрать трассировку
По умолчанию сбор данных профилирования не выполняется, если он не запрошен явно. Иными словами,
если профилирование не включено, накладные расходы пренебрежимо малы. Можно задать разные значения XRAY_OPTIONS, чтобы
настроить, когда профилировщик начинает сбор данных и как именно он это делает.
XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic verbosity=1" ./test
==74394==XRay: Log file in 'xray-log.test.14imlN'
Start
Finish
==74394==Cleaned up log for TID: 74394Преобразование трассировки
Трассировки XRay можно преобразовать в несколько форматов. Формат trace_event очень полезен, потому что
его легко разобрать, и уже есть ряд инструментов, которые его поддерживают, поэтому мы будем использовать именно его:
llvm-xray convert --symbolize --instr_map=./test --output-format=trace_event xray-log.test.14imlN | gzip > test-trace.txt.gzВизуализируйте трассировку
Можно использовать веб-интерфейсы, такие как speedscope.app или Perfetto.
Хотя Perfetto упрощает визуализацию нескольких потоков и выполнение запросов к данным, speedscope лучше подходит для построения флеймграфа и представления данных в режиме «сэндвич».
Хронологический порядок

Перекос влево

Сэндвич

Ознакомьтесь с документацией
- SYSTEM INSTRUMENT — Добавьте или удалите точки инструментирования.
- system.instrumentation — Просматривайте инструментированные точки.
- system.symbols — Просматривайте символы, чтобы добавлять точки инструментирования.
- system.trace_log — Просматривайте данные, собранные с помощью точек инструментирования.
- XRay Instrumentation
- Документация Debugging with XRay с дополнительными сведениями.