内存分配分析
ClickHouse 使用 jemalloc 作为其全局分配器。Jemalloc 自带了一些用于内存分配采样和分析的工具。
为了让内存分配分析更方便,ClickHouse 和 Keeper 允许通过配置、查询设置、SYSTEM 命令以及 Keeper 中的四字命令(4LW)来控制采样。
此外,采样数据可以以 JemallocSample 类型收集到 system.trace_log 表中。
本指南适用于 25.9 及以上版本。
对于更早的版本,请参阅25.9 之前版本的内存分配分析。
采样内存分配
如需在 jemalloc 中对内存分配进行采样和分析,你需要在启动 ClickHouse/Keeper 时启用配置项 jemalloc_enable_global_profiler。
jemalloc 将对内存分配进行采样,并在内部存储相关信息。
你也可以通过 jemalloc_enable_profiler 设置来为每个查询启用内存分配采样。
由于 ClickHouse 是一个内存分配密集型应用程序,jemalloc 采样可能会带来性能开销。
在 system.trace_log 中存储 jemalloc 采样数据
你可以将所有 jemalloc 采样数据以 JemallocSample 类型存储到 system.trace_log 中。
要在全局范围内启用此功能,可以使用配置项 jemalloc_collect_global_profile_samples_in_trace_log。
由于 ClickHouse 是一个内存分配非常密集的应用程序,在 system.trace_log 中收集所有样本可能会带来较高负载。
你也可以通过使用 jemalloc_collect_profile_samples_in_trace_log 设置,为单个查询启用该功能。
使用 system.trace_log 分析查询内存使用情况的示例
首先,我们需要在启用 jemalloc profiler 的情况下运行查询,并将该查询的样本收集到 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:
然后对其进行查询,以获取我们在每个时间点运行的查询的内存使用情况:
我们还可以找出内存使用量最高的时间点:
我们可以利用该结果查看在该时间点上哪些位置的活跃内存分配最多:
刷新堆内存剖析文件
默认情况下,堆剖析文件会生成在 /tmp/jemalloc_clickhouse._pid_._seqnum_.heap 中,其中 _pid_ 是 ClickHouse 的 PID,_seqnum_ 是当前堆剖析文件的全局序号。
对于 Keeper,默认文件为 /tmp/jemalloc_keeper._pid_._seqnum_.heap,并遵循相同规则。
你可以通过运行以下命令,让 jemalloc 将当前剖析文件刷新到磁盘:
- ClickHouse
- Keeper
它会返回已刷新的剖析文件的位置。
你可以通过在 MALLOC_CONF 环境变量中追加 prof_prefix 选项来定义不同的存储位置。
例如,如果你希望在 /data 目录中生成剖析文件,并将文件名前缀设置为 my_current_profile,可以使用如下环境变量来运行 ClickHouse/Keeper:
生成的文件名将由前缀、PID 和序列号组成。
分析堆内存剖析数据
在生成堆内存剖析数据之后,需要对其进行分析。
为此,可以使用 jemalloc 提供的工具 jeprof。它可以通过多种方式安装:
- 使用系统的包管理器
- 克隆 jemalloc 仓库 并在根目录运行
autogen.sh。这样会在bin目录中生成jeprof脚本
可以使用 jeprof 从堆内存分析结果生成多种不同的输出格式。
建议运行 jeprof --help 来查看该工具的用法以及提供的各类选项。
通常情况下,jeprof 命令的用法如下:
如果你想比较在两个分析概要之间发生了哪些分配,可以设置 base 参数:
示例
- 如果你想生成一个文本文件,使每个过程各写在单独一行:
- 如果你想生成带有调用关系图的 PDF 文件:
生成火焰图
jeprof 可以生成用于构建火焰图的折叠后调用栈。
需要使用 --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)中的内存分配情况,这些信息从所有 arena 聚合而来。
Prometheus
来自 asynchronous_metrics 的所有与 jemalloc 相关的指标,也会通过 ClickHouse 和 Keeper 中的 Prometheus 端点对外暴露。
Keeper 中的 jmst 4LW 命令
Keeper 支持 jmst 4LW 命令,其返回基础分配器统计信息: