Профилирование выделений памяти
ClickHouse использует jemalloc в качестве глобального аллокатора. Jemalloc включает инструменты для сэмплирования и профилирования выделений памяти.
ClickHouse и Keeper позволяют управлять сэмплированием с помощью конфигураций, настроек запроса, команд SYSTEM и команд с четырьмя буквами (4LW) в Keeper. Существует несколько способов просмотреть результаты:
- Собирайте сэмплы в
system.trace_logс типомJemallocSampleдля анализа на уровне отдельных запросов. - Просматривайте статистику памяти в реальном времени и получайте профили кучи через встроенный веб‑интерфейс jemalloc (26.2+).
- Запрашивайте текущий профиль кучи напрямую из SQL с помощью
system.jemalloc_profile_text(26.2+). - Сбрасывайте профили кучи на диск и анализируйте их с помощью
jeprof.
Это руководство применимо к версиям 25.9+. Для более старых версий см. раздел профилирование выделений памяти для версий до 25.9.
Сэмплирование выделений памяти
Чтобы выполнять сэмплирование и профилирование выделений памяти, запустите ClickHouse/Keeper с включённой настройкой jemalloc_enable_global_profiler:
jemalloc будет выборочно отслеживать выделения памяти и сохранять эту информацию во внутренних структурах.
Вы также можете включить сэмплирование по каждому запросу с помощью настройки jemalloc_enable_profiler.
Поскольку ClickHouse — приложение с интенсивным использованием выделения памяти, выборочное отслеживание jemalloc может привести к дополнительным накладным расходам и снижению производительности.
Хранение выборок jemalloc в system.trace_log
Вы можете хранить выборки jemalloc в system.trace_log с типом записи JemallocSample.
Чтобы включить это глобально, используйте параметр конфигурации jemalloc_collect_global_profile_samples_in_trace_log:
Поскольку ClickHouse — приложение с большим количеством операций выделения памяти, сбор всех сэмплов в system.trace_log может привести к значительной нагрузке.
Вы также можете включить это для отдельного запроса, используя настройку jemalloc_collect_profile_samples_in_trace_log.
Пример анализа использования памяти запросом
Сначала выполните запрос с включённым профилировщиком памяти jemalloc и соберите сэмплы в system.trace_log:
Если ClickHouse был запущен с jemalloc_enable_global_profiler, вам не нужно включать jemalloc_enable_profiler.
То же самое относится к jemalloc_collect_global_profile_samples_in_trace_log и jemalloc_collect_profile_samples_in_trace_log.
Очистим system.trace_log:
Затем выполним по нему запрос, чтобы получить накопленное использование памяти во времени:
Найдите момент, когда использование памяти было максимальным:
Используя этот результат, определите, какие стеки выделения памяти были наиболее активны в момент пика:
Веб-интерфейс Jemalloc
Этот раздел актуален для версий 26.2+.
ClickHouse предоставляет встроенный веб-интерфейс для просмотра статистики памяти jemalloc по конечной точке HTTP /jemalloc.
В нем в реальном времени отображаются метрики памяти с графиками, включая allocated, active, resident и mapped memory, а также статистика по аренам и bin.
Вы также можете получать глобальные профили кучи и профили кучи отдельных запросов прямо из интерфейса.
- ClickHouse
- Keeper
Интерфейс сервера содержит все вкладки: Summary, Allocations, Arenas, Operations, Global Profiler, Query Profiler и Raw Output.
Интерфейс Keeper доступен на порту HTTP-контроля. Этот порт по умолчанию отключен, и его нужно явно включить, задав keeper_server.http_control.port в конфигурации Keeper:
После включения интерфейс предоставляет те же визуализации, что и сервер, — Summary, Allocations, Arenas, Operations, Global Profiler и Raw Output — за исключением вкладки Query Profiler, так как для нее требуются SQL и system.trace_log.
Порт HTTP-контроля Keeper не имеет аутентификации на уровне приложения. В отличие от jemalloc UI сервера ClickHouse, где все запросы данных проходят через SQL HTTP handler и требуют имени пользователя и пароля, конечные точки REST API Keeper не требуют аутентификации. Это соответствует другим конечным точкам HTTP-контроля Keeper (команды, хранилище, дашборд).
Ограничьте доступ к этому порту с помощью сетевых средств: привяжите Keeper к localhost, используйте правила firewall или разместите его за обратным прокси с аутентификацией. Если listen_host не настроен, Keeper по умолчанию слушает только localhost.
Keeper также предоставляет конечные точки REST API для программного доступа:
GET /jemalloc/stats— необработанный выводmalloc_stats_printGET /jemalloc/status— состояние профилирования в формате JSON (prof_enabled,prof_active,thread_active_init,lg_sample)GET /jemalloc/profile?format={collapsed|raw}— принудительно сбрасывает профиль кучи с серверной символизацией, возвращает collapsed stacks, подходящие для отрисовки флеймграфа (по умолчанию), либо необработанный дамп jemalloc
Получение heap-профилей через SQL
Этот раздел актуален для версий 26.2+.
Системная таблица system.jemalloc_profile_text позволяет получать и просматривать текущий heap-профиль jemalloc непосредственно из SQL, без необходимости использования внешних инструментов или предварительной записи на диск.
Таблица содержит один столбец:
| Column | Type | Description |
|---|---|---|
line | String | Строка из символизированного heap-профиля jemalloc. |
Вы можете выполнять запрос к таблице напрямую — нет необходимости предварительно сбрасывать heap-профиль:
Формат вывода
Формат вывода управляется параметром jemalloc_profile_text_output_format, который поддерживает три значения:
raw— необработанный heap-профиль в том виде, в котором его формирует jemalloc.symbolized— формат, совместимый сjeprof, со встроенными символами функций. Поскольку символы уже встроены,jeprofможет анализировать вывод без необходимости в исполняемом файле ClickHouse.collapsed(по умолчанию) — свернутые стеки, совместимые с FlameGraph: по одному стеку на строку с указанием количества байт.
Например, чтобы получить необработанный профиль:
Чтобы получить символизированный вывод:
Дополнительные настройки
jemalloc_profile_text_symbolize_with_inline(Bool, по умолчанию:true) — Нужно ли включать inline‑кадры при символизации. Отключение этого параметра значительно ускоряет символизацию, но снижает точность, так как встроенные вызовы функций не будут отображаться в стеках. Влияет только на форматыsymbolizedиcollapsed.jemalloc_profile_text_collapsed_use_count(Bool, по умолчанию:false) — При использовании форматаcollapsedагрегировать по количеству выделений памяти, а не по байтам.
Пример: построение флеймграфа по SQL
Поскольку формат вывода по умолчанию — collapsed, вы можете передать результат напрямую в FlameGraph:
Чтобы построить flame graph по числу аллокаций, а не по объёму в байтах:
Сброс профилей кучи на диск
Если вам нужно сохранить профили кучи в виде файлов для офлайн-анализа с помощью jeprof, вы можете сбросить их на диск.
По умолчанию файл профиля кучи создаётся в /tmp/jemalloc_clickhouse._pid_._seqnum_.heap, где _pid_ — это PID ClickHouse, а _seqnum_ — глобальный порядковый номер для текущего профиля кучи.
Для Keeper файл по умолчанию — /tmp/jemalloc_keeper._pid_._seqnum_.heap и подчиняется тем же правилам.
Чтобы сбросить текущий профиль:
- ClickHouse
- Keeper
Команда вернёт путь к сброшенному профилю.
Другое местоположение можно задать, дополнив переменную окружения MALLOC_CONF опцией prof_prefix.
Например, если вы хотите генерировать профили в каталоге /data, где префиксом имени файла будет my_current_profile, вы можете запустить ClickHouse/Keeper со следующей переменной окружения:
К префиксу имени сгенерированного файла будут добавлены PID и порядковый номер.
Анализ файлов профилей кучи с помощью jeprof
После того как профили кучи были сброшены на диск, их можно проанализировать с помощью инструмента jemalloc под названием jeprof. Его можно установить несколькими способами:
- С помощью системного менеджера пакетов
- Клонировать репозиторий jemalloc и запустить
autogen.shиз корневого каталога. В результате в каталогеbinпоявится скриптjeprof.
Доступно множество различных форматов вывода. Запустите jeprof --help, чтобы увидеть полный список опций.
Символизированные профили кучи
Начиная с версии 26.1+ ClickHouse автоматически генерирует символизированные профили кучи при выполнении команды SYSTEM JEMALLOC FLUSH PROFILE.
Символизированный профиль (с расширением .symbolized) содержит встроенные символы функций и может анализироваться с помощью jeprof без необходимости в исполняемом файле ClickHouse.
Например, при выполнении:
ClickHouse вернёт путь к символизированному профилю (например, /tmp/jemalloc_clickhouse.12345.0.heap.symbolized).
Затем вы можете напрямую проанализировать его с помощью jeprof:
Бинарный файл не требуется: При использовании символизированных профилей (файлы .symbolized) вам не нужно указывать путь к бинарнику ClickHouse для jeprof. Это значительно упрощает анализ профилей на разных машинах или после обновления бинарного файла.
Если у вас есть старый несимволизированный профиль кучи и по-прежнему есть доступ к бинарному файлу ClickHouse, вы можете использовать традиционный подход:
Для несимволизированных профилей jeprof использует addr2line для генерации стек-трейсов, что может работать очень медленно.
В таком случае рекомендуется установить альтернативную реализацию этого инструмента.
В качестве альтернативы можно использовать llvm-addr2line — он работает не хуже (но обратите внимание, что llvm-objdump не совместим с jeprof).
После этого используйте его следующим образом: jeprof --tools addr2line:/usr/bin/llvm-addr2line,nm:/usr/bin/llvm-nm,objdump:/usr/bin/objdump,c++filt:/usr/bin/llvm-cxxfilt
При сравнении двух профилей вы можете использовать аргумент --base:
Примеры
Использование символизированных профилей (рекомендуется):
- Создайте текстовый файл, в котором каждая процедура указана в отдельной строке:
- Сгенерируйте PDF-файл с графом вызовов:
Использование несиволизированных профилей (требуется бинарник):
- Сгенерируйте текстовый файл, в котором каждая процедура указана в отдельной строке:
- Создайте PDF-файл с графом вызовов:
Построение flame-графа
jeprof позволяет получать свернутые стеки вызовов для построения flame-графов.
Для этого следует использовать аргумент --collapsed:
Или с профилем без символов:
После этого вы можете использовать различные инструменты для визуализации свернутых стеков.
Самый популярный из них — FlameGraph, который содержит скрипт flamegraph.pl:
Еще один полезный инструмент — speedscope, который позволяет более интерактивно анализировать собранные стеки.
Дополнительные параметры профилировщика
У jemalloc есть множество параметров, относящихся к профилировщику. Ими можно управлять, изменяя переменную окружения MALLOC_CONF.
Например, интервал между выборками операций выделения памяти можно контролировать с помощью lg_prof_sample.
Если вы хотите создавать дамп профиля кучи каждые N байт, вы можете включить это с помощью lg_prof_interval.
Рекомендуется ознакомиться со справочной страницей jemalloc для получения полного перечня параметров.
Другие ресурсы
ClickHouse/Keeper предоставляют метрики, связанные с jemalloc, множеством разных способов.
Важно понимать, что ни одна из этих метрик не синхронизирована с другими, и значения со временем могут расходиться.
Системная таблица asynchronous_metrics
Системная таблица jemalloc_bins
Содержит информацию о выделении памяти, выполненном через аллокатор jemalloc в разных классах размеров (bins), агрегированную по всем аренам.
Системная таблица jemalloc_stats (26.2+)
Возвращает полный вывод malloc_stats_print() в виде единой строки. Эквивалентно команде SYSTEM JEMALLOC STATS.
Prometheus
Все метрики, связанные с jemalloc из asynchronous_metrics, также доступны через конечную точку Prometheus как в ClickHouse, так и в Keeper.
Команда jmst 4LW в Keeper
Keeper поддерживает команду jmst 4LW, которая возвращает базовую статистику аллокатора: