跳转到主要内容
ClickHouse 使用 jemalloc 作为全局内存分配器。Jemalloc 自带一些用于分配采样和性能分析的工具。 为了让内存分配分析更方便,除了 Keeper 中的四字命令 (4LW) 外,还提供了 SYSTEM 命令。

对内存分配进行采样并写出堆内存剖析

如果你想在 jemalloc 中对内存分配进行采样和剖析,需要在启动 ClickHouse/Keeper 时通过环境变量 MALLOC_CONF 启用 profiling:
MALLOC_CONF=background_thread:true,prof:true,prof_active:true
jemalloc 会对内存分配进行采样,并在内部保存相关信息。 你可以运行以下命令,让 jemalloc 将当前 profile flush 到磁盘:
SYSTEM JEMALLOC FLUSH PROFILE
默认情况下,堆内存剖析文件会生成在 /tmp/jemalloc_clickhouse._pid_._seqnum_.heap,其中 _pid_ 是 ClickHouse 的 PID,_seqnum_ 是当前堆内存剖析的全局序列号。 对于 Keeper,默认文件为 /tmp/jemalloc_keeper._pid_._seqnum_.heap,规则相同。 你也可以通过在 MALLOC_CONF 环境变量中追加 prof_prefix 选项来指定其他位置。 例如,如果你想在 /data 目录中生成剖析文件,并将文件名前缀设为 my_current_profile,可以使用以下环境变量运行 ClickHouse/Keeper:
MALLOC_CONF=background_thread:true,prof:true,prof_prefix:/data/my_current_profile
生成的文件名将附带前缀、PID 和序列号。

分析堆内存剖析

生成堆内存剖析后,需要对其进行分析。 为此,可以使用 jemalloc 的工具 jeprof。它有多种安装方式:
  • 使用系统的软件包管理器
  • 克隆 jemalloc 仓库,并在根目录运行 autogen.sh。这样会在 bin 文件夹中生成 jeprof 脚本
jeprof 使用 addr2line 生成调用栈,这个过程可能会非常慢。 如果遇到这种情况,建议安装该工具的另一种实现
git clone https://github.com/gimli-rs/addr2line.git --depth=1 --branch=0.23.0
cd addr2line
cargo build --features bin --release
cp ./target/release/addr2line path/to/current/addr2line
可以使用 jeprof 从堆内存剖析中生成多种不同的输出格式。 建议运行 jeprof --help,了解该工具的用法以及它提供的各种选项。 通常,jeprof 命令的用法如下:
jeprof path/to/binary path/to/heap/profile --output_format [ > output_file]
如果你想比较两个 profile 之间有哪些内存分配,可设置 base 参数:
jeprof path/to/binary --base path/to/first/heap/profile path/to/second/heap/profile --output_format [ > output_file]

示例

  • 如果你想生成一个文本文件,并将每个过程分别写在一行中:
jeprof path/to/binary path/to/heap/profile --text > result.txt
  • 如果你想生成包含调用图的 PDF 文件:
jeprof path/to/binary path/to/heap/profile --pdf > result.pdf

生成火焰图

jeprof 可生成用于构建火焰图的折叠栈。 你需要使用 --collapsed 参数:
jeprof path/to/binary path/to/heap/profile --collapsed > result.collapsed
之后,你可以使用许多不同的工具将折叠栈可视化。 其中最常用的是 FlameGraph,其中包含一个名为 flamegraph.pl 的脚本:
cat result.collapsed | /path/to/FlameGraph/flamegraph.pl --color=mem --title="Allocation Flame Graph" --width 2400 > result.svg
另一个有趣的工具是 speedscope,它可以让你以更直观的交互方式分析已采集的调用栈。

在运行时控制内存分配剖析器

如果 ClickHouse/Keeper 在启动时启用了 剖析器,则支持在运行时禁用/启用内存分配分析的额外命令。 使用这些命令后,就可以更方便地只分析特定时间间隔。 要禁用剖析器:
SYSTEM JEMALLOC DISABLE PROFILE
要启用剖析器:
SYSTEM JEMALLOC ENABLE PROFILE
也可以通过设置 prof_active 选项来控制剖析器的初始状态;该选项默认启用。 例如,如果你不想在启动期间对内存分配进行采样,而只想在启动完成后采样,可以启用分析器。你可以使用以下环境变量启动 ClickHouse/Keeper:
MALLOC_CONF=background_thread:true,prof:true,prof_active:false
稍后可启用剖析器。

剖析器的其他选项

jemalloc 提供了许多与剖析器相关的选项,这些选项可通过修改 MALLOC_CONF 环境变量来控制。 例如,可以使用 lg_prof_sample 控制分配样本之间的时间间隔。 如果你想每分配 N 个字节就转储一次堆内存剖析,可以通过 lg_prof_interval 启用。 建议查阅 jemalloc参考页,获取完整的选项列表。

其他资源

ClickHouse/Keeper 会通过多种不同方式暴露与 jemalloc 相关的指标。
警告请务必注意,这些指标彼此之间并未同步,因此其值可能会出现偏差。

系统表 asynchronous_metrics

SELECT *
FROM system.asynchronous_metrics
WHERE metric LIKE '%jemalloc%'
FORMAT Vertical
参考

系统表 jemalloc_bins

包含通过 jemalloc 分配器在不同大小类 (bins) 中进行的内存分配信息,汇总自所有 Arena。 参考

Prometheus

asynchronous_metrics 中所有与 jemalloc 相关的指标,也会通过 ClickHouse 和 Keeper 的 Prometheus 端点对外暴露。 参考

Keeper 中的 jmst 4LW 命令

Keeper 支持 jmst 4LW 命令,该命令会返回基础分配器统计信息
echo jmst | nc localhost 9181
最后修改于 2026年6月10日