O ClickHouse usa o jemalloc como alocador global. O jemalloc inclui ferramentas de amostragem e profiling de alocação.
O ClickHouse e o Keeper permitem controlar a amostragem usando configurações, configurações de consulta, comandos SYSTEM e comandos de quatro letras (4LW) no Keeper. Há várias maneiras de inspecionar os resultados:
- Coletar amostras em
system.trace_logsob o tipoJemallocSamplepara análise por consulta. - Visualizar estatísticas de memória em tempo real e obter perfis de heap por meio da interface web integrada do jemalloc (26.2+).
- Consultar o perfil de heap atual diretamente via SQL usando
system.jemalloc_profile_text(26.2+). - Gravar perfis de heap em disco e analisá-los com
jeprof.
Amostragem de alocações
Para fazer a amostragem e traçar o perfil das alocações, inicie o ClickHouse/Keeper com a configuração jemalloc_enable_global_profiler habilitada:
<clickhouse>
<jemalloc_enable_global_profiler>1</jemalloc_enable_global_profiler>
</clickhouse>jemalloc fará a amostragem das alocações e armazenará as informações internamente.
Você também pode ativar a amostragem por consulta usando a configuração jemalloc_enable_profiler.
Armazenando amostras do jemalloc em system.trace_log
Você pode armazenar amostras do jemalloc em system.trace_log como o tipo JemallocSample.
Para habilitar isso globalmente, use a configuração jemalloc_collect_global_profile_samples_in_trace_log:
<clickhouse>
<jemalloc_collect_global_profile_samples_in_trace_log>1</jemalloc_collect_global_profile_samples_in_trace_log>
</clickhouse>Você também pode habilitar isso por consulta usando a configuração jemalloc_collect_profile_samples_in_trace_log.
Exemplo: analisando o uso de memória de uma consulta
Primeiro, execute uma consulta com o profiler do jemalloc habilitado e colete as amostras em system.trace_log:
SELECT *
FROM numbers(1000000)
ORDER BY number DESC
SETTINGS max_bytes_ratio_before_external_sort = 0
FORMAT `Null`
SETTINGS jemalloc_enable_profiler = 1, jemalloc_collect_profile_samples_in_trace_log = 1
Query id: 8678d8fe-62c5-48b8-b0cd-26851c62dd75
Ok.
0 rows in set. Elapsed: 0.009 sec. Processed 1.00 million rows, 8.00 MB (108.58 million rows/s., 868.61 MB/s.)
Peak memory usage: 12.65 MiB.Faça o flush de system.trace_log:
SYSTEM FLUSH LOGS trace_logEm seguida, consulte-o para obter o uso cumulativo de memória ao longo do tempo:
WITH per_bucket AS
(
SELECT
event_time_microseconds AS bucket_time,
sum(size) AS bucket_sum
FROM system.trace_log
WHERE trace_type = 'JemallocSample'
AND query_id = '8678d8fe-62c5-48b8-b0cd-26851c62dd75'
GROUP BY bucket_time
)
SELECT
bucket_time,
sum(bucket_sum) OVER (
ORDER BY bucket_time ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS cumulative_size,
formatReadableSize(cumulative_size) AS cumulative_size_readable
FROM per_bucket
ORDER BY bucket_timeEncontre o momento em que o uso de memória foi mais alto:
SELECT
argMax(bucket_time, cumulative_size),
max(cumulative_size)
FROM
(
WITH per_bucket AS
(
SELECT
event_time_microseconds AS bucket_time,
sum(size) AS bucket_sum
FROM system.trace_log
WHERE trace_type = 'JemallocSample'
AND query_id = '8678d8fe-62c5-48b8-b0cd-26851c62dd75'
GROUP BY bucket_time
)
SELECT
bucket_time,
sum(bucket_sum) OVER (
ORDER BY bucket_time ASC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS cumulative_size,
formatReadableSize(cumulative_size) AS cumulative_size_readable
FROM per_bucket
ORDER BY bucket_time
)Usando esse resultado, veja quais pilhas de alocação estavam mais ativas no momento de pico:
SELECT
concat(
'\n',
arrayStringConcat(
arrayMap(
(x, y) -> concat(x, ': ', y),
arrayMap(x -> addressToLine(x), allocation_trace),
arrayMap(x -> demangle(addressToSymbol(x)), allocation_trace)
),
'\n'
)
) AS symbolized_trace,
sum(s) AS per_trace_sum
FROM
(
SELECT
ptr,
sum(size) AS s,
argMax(trace, event_time_microseconds) AS allocation_trace
FROM system.trace_log
WHERE trace_type = 'JemallocSample'
AND query_id = '8678d8fe-62c5-48b8-b0cd-26851c62dd75'
AND event_time_microseconds <= '2025-09-04 11:56:21.737139'
GROUP BY ptr
HAVING s > 0
)
GROUP BY ALL
ORDER BY per_trace_sum ASCInterface web do jemalloc
O ClickHouse fornece uma interface web integrada para visualizar estatísticas de memória do jemalloc no endpoint HTTP /jemalloc.
Ela exibe métricas de memória em tempo real com gráficos, incluindo memória alocada, ativa, residente e mapeada, além de estatísticas por arena e por bin.
Você também pode buscar perfis de heap globais e por consulta diretamente pela interface web.
http://localhost:8123/jemallocA interface web do servidor inclui todas as abas: Summary, Allocations, Arenas, Operations, Global Profiler, Query Profiler e Raw Output.
http://localhost:9182/jemallocA interface web do Keeper está disponível na porta de controle HTTP. Essa porta fica desabilitada por padrão e deve ser habilitada explicitamente definindo keeper_server.http_control.port na configuração do Keeper:
<clickhouse>
<keeper_server>
<http_control>
<port>9182</port>
</http_control>
</keeper_server>
</clickhouse>Depois de habilitada, a interface web fornece as mesmas visualizações que o servidor — Summary, Allocations, Arenas, Operations, Global Profiler e Raw Output — exceto pela aba Query Profiler, que requer SQL e system.trace_log.
O Keeper também expõe endpoints de API REST para acesso programático:
GET /jemalloc/stats— saída bruta demalloc_stats_printGET /jemalloc/status— estado do profiling em JSON (prof_enabled,prof_active,thread_active_init,lg_sample)GET /jemalloc/profile?format={collapsed|raw}— gera um perfil de heap com simbolização no lado do servidor e retorna collapsed stacks adequadas para renderização de flame graph (padrão) ou o dump bruto do jemalloc
Obtendo perfis de heap por SQL
A tabela de sistema system.jemalloc_profile_text permite obter e visualizar o perfil de heap atual do jemalloc diretamente por SQL, sem precisar de ferramentas externas nem de gravá-lo em disco antes.
A tabela tem uma única coluna:
| Coluna | Tipo | Descrição |
|---|---|---|
line |
String | Linha do perfil de heap do jemalloc simbolizado. |
Você pode consultar a tabela diretamente — não é necessário gravar um perfil de heap antes:
SELECT * FROM system.jemalloc_profile_textFormato de saída
O formato de saída é controlado pela configuração jemalloc_profile_text_output_format, que oferece suporte a três valores:
raw— perfil de heap bruto, gerado pelo jemalloc.symbolized— formato compatível com o jeprof, com símbolos de função incorporados. Como os símbolos já estão incorporados, ojeprofpode analisar a saída sem precisar do binário do ClickHouse.collapsed(padrão) — pilhas colapsadas compatíveis com FlameGraph, uma pilha por linha com a contagem de bytes.
Por exemplo, para obter o perfil bruto:
SELECT * FROM system.jemalloc_profile_text
SETTINGS jemalloc_profile_text_output_format = 'raw'Para obter uma saída simbolizada:
SELECT * FROM system.jemalloc_profile_text
SETTINGS jemalloc_profile_text_output_format = 'symbolized'Configurações adicionais
jemalloc_profile_text_symbolize_with_inline(Bool, padrão:true) — Define se frames inline devem ser incluídos na simbolização. Desabilitar isso acelera significativamente a simbolização, mas reduz a precisão, pois chamadas de função inline não aparecerão nas stacks. Afeta apenas os formatossymbolizedecollapsed.jemalloc_profile_text_collapsed_use_count(Bool, padrão:false) — Ao usar o formatocollapsed, agrega por contagem de alocações em vez de bytes.
Exemplo: gerando um flame graph com SQL
Como o formato de saída padrão é collapsed, você pode passar a saída diretamente para o FlameGraph:
clickhouse-client -q "SELECT * FROM system.jemalloc_profile_text" | flamegraph.pl --color=mem --title="Allocation Flame Graph" --width 2400 > result.svgPara gerar um flame graph com base na contagem de alocações, em vez de bytes:
clickhouse-client -q "SELECT * FROM system.jemalloc_profile_text SETTINGS jemalloc_profile_text_collapsed_use_count = 1" | flamegraph.pl --color=mem --title="Allocation Count Flame Graph" --width 2400 > result.svgGravando perfis de heap no disco
Se você precisar salvar perfis de heap como arquivos para análise offline com jeprof, poderá gravá-los no disco.
Por padrão, o arquivo de perfil de heap será gerado em /tmp/jemalloc_clickhouse._pid_._seqnum_.heap, em que _pid_ é o PID do ClickHouse e _seqnum_ é o número de sequência global do perfil de heap atual.
No Keeper, o arquivo padrão é /tmp/jemalloc_keeper._pid_._seqnum_.heap e segue as mesmas regras.
Para gravar o perfil atual:
SYSTEM JEMALLOC FLUSH PROFILEEle retornará o local do perfil gravado.
echo jmfp | nc localhost 9181É possível definir outro local adicionando a opção prof_prefix à variável de ambiente MALLOC_CONF.
Por exemplo, se você quiser gerar perfis na pasta /data, em que o prefixo do nome do arquivo será my_current_profile, poderá executar o ClickHouse/Keeper com a seguinte variável de ambiente:
MALLOC_CONF=prof_prefix:/data/my_current_profileO PID e o número de sequência serão acrescentados ao prefixo do arquivo gerado.
Analisando arquivos de perfil de heap com jeprof
Após gravar os perfis de heap em disco, eles podem ser analisados usando a ferramenta do jemalloc chamada jeprof. Ela pode ser instalada de várias formas:
- Usando o gerenciador de pacotes do sistema
- Clonando o repositório do jemalloc e executando
autogen.sha partir da pasta raiz. Isso disponibilizará o scriptjeprofna pastabin
Há vários formatos de saída disponíveis. Execute jeprof --help para ver a lista completa de opções.
Perfis de heap simbolizados
A partir da versão 26.1+, o ClickHouse gera automaticamente perfis de heap simbolizados quando você executa SYSTEM JEMALLOC FLUSH PROFILE.
O perfil simbolizado (com a extensão .symbolized) contém símbolos de função incorporados e pode ser analisado com o jeprof sem exigir o binário do ClickHouse.
Por exemplo, quando você executa:
SYSTEM JEMALLOC FLUSH PROFILEO ClickHouse retornará o caminho para o profile simbolizado (por exemplo, /tmp/jemalloc_clickhouse.12345.0.heap.symbolized).
Em seguida, você poderá analisá-lo diretamente com jeprof:
jeprof /tmp/jemalloc_clickhouse.12345.0.heap.symbolized --output_format [ > output_file]Se você tiver um perfil de heap mais antigo, sem símbolos, e ainda tiver acesso ao binário do ClickHouse, poderá usar a abordagem tradicional:
jeprof path/to/clickhouse path/to/heap/profile --output_format [ > output_file]Ao comparar dois perfis, você pode usar o argumento --base:
jeprof --base /path/to/first.heap.symbolized /path/to/second.heap.symbolized --output_format [ > output_file]Exemplos
Usando perfis simbolizados (recomendado):
- Gere um arquivo de texto com cada procedimento em uma linha:
jeprof /tmp/jemalloc_clickhouse.12345.0.heap.symbolized --text > result.txt- Gere um arquivo PDF com o grafo de chamadas:
jeprof /tmp/jemalloc_clickhouse.12345.0.heap.symbolized --pdf > result.pdfUsando perfis não simbolizados (requer o binário):
- Gere um arquivo de texto com cada procedimento em uma linha:
jeprof /path/to/clickhouse /tmp/jemalloc_clickhouse.12345.0.heap --text > result.txt- Gere um arquivo PDF com um grafo de chamadas:
jeprof /path/to/clickhouse /tmp/jemalloc_clickhouse.12345.0.heap --pdf > result.pdfGerando um flame graph
jeprof permite gerar pilhas colapsadas para criar flame graphs.
Você precisa usar o argumento --collapsed:
jeprof /tmp/jemalloc_clickhouse.12345.0.heap.symbolized --collapsed > result.collapsedOu com um perfil sem símbolos:
jeprof /path/to/clickhouse /tmp/jemalloc_clickhouse.12345.0.heap --collapsed > result.collapsedDepois disso, você pode usar várias ferramentas para visualizar pilhas colapsadas.
A mais popular é o FlameGraph, que contém um script chamado flamegraph.pl:
cat result.collapsed | /path/to/FlameGraph/flamegraph.pl --color=mem --title="Allocation Flame Graph" --width 2400 > result.svgOutra ferramenta interessante é o speedscope, que permite analisar as stacks coletadas de forma mais interativa.
Opções adicionais para o profiler
O jemalloc oferece muitas opções relacionadas ao profiler. Elas podem ser controladas modificando a variável de ambiente MALLOC_CONF.
Por exemplo, o intervalo entre as amostras de alocação pode ser controlado com lg_prof_sample.
Se você quiser gerar o heap profile a cada N bytes, pode ativá-lo usando lg_prof_interval.
Recomenda-se consultar a página de referência do jemalloc para obter uma lista completa das opções.
Outros recursos
ClickHouse/Keeper expõem métricas relacionadas ao jemalloc de várias formas.
Tabela de sistema asynchronous_metrics
SELECT *
FROM system.asynchronous_metrics
WHERE metric LIKE '%jemalloc%'
FORMAT VerticalTabela de sistema jemalloc_bins
Contém informações sobre alocações de memória feitas pelo alocador jemalloc em diferentes classes de tamanho (bins), agregadas a partir de todas as arenas.
Tabela do sistema jemalloc_stats (26.2+)
Retorna toda a saída de malloc_stats_print() como uma única string. Equivalente ao comando SYSTEM JEMALLOC STATS.
SELECT * FROM system.jemalloc_statsPrometheus
Todas as métricas relacionadas ao jemalloc de asynchronous_metrics também são expostas por meio do endpoint do Prometheus, tanto no ClickHouse quanto no Keeper.
Comando 4LW jmst no Keeper
O Keeper é compatível com o comando 4LW jmst, que retorna estatísticas básicas do alocador:
echo jmst | nc localhost 9181