跳至主要内容

内存分配分析

ClickHouse 使用 jemalloc 作为其全局分配器,它带有一些用于分配采样和分析的工具。
为了使内存分配分析更方便,在 Keeper 中提供了 4LW 命令以及 SYSTEM 命令。

采样分配和刷新堆分析

如果我们想在 jemalloc 中采样和分析内存分配,我们需要使用环境变量 MALLOC_CONF 启动 ClickHouse/Keeper 并启用分析功能。

MALLOC_CONF=background_thread:true,prof:true

jemalloc 将采样内存分配并将信息存储在内部。

我们可以通过运行以下命令告诉 jemalloc 刷新当前分析结果

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
  • 克隆 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]

如果我们想比较两个分析结果之间的内存分配,可以设置基本参数

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 ILIKE '%jemalloc%'
FORMAT Vertical

参考

系统表 jemalloc_bins

包含有关通过 jemalloc 分配器在不同大小类别(bin)中进行的内存分配的信息,这些信息来自所有区域的汇总。

参考

Prometheus

来自 asynchronous_metrics 的所有 jemalloc 相关指标也通过 ClickHouse 和 Keeper 中的 Prometheus 端点公开。

参考

Keeper 中的 jmst 4LW 命令

Keeper 支持 jmst 4LW 命令,该命令返回 基本分配器统计信息

示例

echo jmst | nc localhost 9181