Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Профилирование ClickHouse с помощью XRay из LLVM

Типы профилировщиков

В 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 лучше подходит для построения флеймграфа и представления данных в режиме «сэндвич».

Хронологический порядок

time-order

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

перекос влево

Сэндвич

сэндвич

Ознакомьтесь с документацией

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