ClickHouse 使用 jemalloc 作为全局内存分配器。Jemalloc 自带一些用于分配采样和性能分析的工具。
为了让内存分配分析更方便,除了 Keeper 中的四字命令 (4LW) 外,还提供了 SYSTEM 命令。
对内存分配进行采样并写出堆内存剖析
如果你想在 jemalloc 中对内存分配进行采样和剖析,需要在启动 ClickHouse/Keeper 时通过环境变量 MALLOC_CONF 启用 profiling:
MALLOC_CONF=background_thread:true,prof:true,prof_active:truejemalloc 会对内存分配进行采样,并在内部保存相关信息。
你可以运行以下命令,让 jemalloc 将当前 profile flush 到磁盘:
SYSTEM JEMALLOC FLUSH PROFILEecho jmfp | nc localhost 9181默认情况下,堆内存剖析文件会生成在 /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 从堆内存剖析中生成多种不同的输出格式。
建议运行 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 PROFILEecho jmdp | nc localhost 9181要启用剖析器:
SYSTEM JEMALLOC ENABLE PROFILEecho jmep | nc localhost 9181也可以通过设置 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