一文教会你!如何利用火焰图快速定位内存泄漏?
从 greptimedb#1733[1] 开始,GreptimeDB 使用 Jemalloc[2] 作为默认的内存分配器,这不仅有助于提升性能和降低内存碎片,也提供了便捷的内存分析功能。在 记一次 Rust 内存泄漏排查之旅 | 经验总结篇[3] 这篇文章中,我们介绍了分析 Rust 应用内存泄漏的几种常用方法,而在本文中将详细介绍基于 Jemalloc 的排查手段。
当您在使用或者开发 GreptimeDB 的过程中,如果遇到内存使用量异常的问题,可以参照本篇文章快速排查和定位可能存在的内存泄漏。
准备工作
安装 flamegraph.pl[4] 脚本
curl -s https://raw.githubusercontent.com/brendangregg/FlameGraph/master/flamegraph.pl > ${HOME}/.local/bin/flamegraph.pl
chmod +x ${HOME}/.local/bin/flamegraph.pl
export PATH=$PATH:${HOME}/.local/bin
flamegraph.pl 是由 Brendan Gregg[5] 编写的用于可视化热点代码调用栈的一个 Perl 脚本。Brendan Gregg 是一位致力于系统性能优化的专家,在此感谢他开发并开源了包括 flamegraph.pl 在内的诸多工具。安装 jeprof 命令
# For Ubuntu
sudo apt install -y libjemalloc-dev
# For Fedora
sudo dnf install jemalloc-devel
对于其他操作系统,您可以通过 pkgs.org[6] 来查找 jeprof 的依赖包。启用 GreptimeDB 的内存分析功能
GreptimeDB 的内存分析功能是一个默认关闭的特性,您可以通过在编译 GreptimeDB 时打开 mem-prof feature 来启用此功能。
cargo build --release -F mem-prof
关于是否应该默认开启 mem-prof 特性,greptimedb#3166[7] 正在进行讨论,您也可以留下您的看法。启动 GreptimeDB 并启用 mem-prof 功能
为了启用内存分析功能,在启动 GreptimeDB 进程时也需要设置环境变量 MALLOC_CONF:
MALLOC_CONF=prof:true <path_to_greptime_binary> standalone start
您可以通过 curl 命令来检查内存分析功能是否正常使用:
curl <greptimedb_ip>:4000/v1/prof/mem
如果内存分析功能已经启用,此命令会返回类似如下的响应:
heap_v2/524288
t*: 125: 136218 [0: 0]
t0: 59: 31005 [0: 0]
...
MAPPED_LIBRARIES:
55aa05c66000-55aa0697a000 r--p 00000000 103:02 40748099 /home/lei/workspace/greptimedb/target/debug/greptime
55aa0697a000-55aa11e74000 r-xp 00d14000 103:02 40748099 /home/lei/workspace/greptimedb/target/debug/greptime
...
否则如果返回 {"error":"Memory profiling is not enabled"} ,则说明 MALLOC_CONF=prof:true 环境变量未正确设置。
关于 内存分析 API 所返回的数据格式,请参考 HEAP PROFILE FORMAT - jemalloc.net[8]。开始您的内存探险!
# 获取内存分配详情
curl <greptimedb_ip>:4000/v1/prof/mem > mem.hprof
# 生成内存分配的火焰图
jeprof <path_to_greptime_binary> ./mem.hprof --collapse | flamegraph.pl > mem-prof.svg
火焰图的最下方为函数栈的栈底,而最上方为栈顶;
火焰图中每一个格子代表一个函数调用,格子下方为此函数的调用者(caller),格子上方为此函数所调用的子函数(callee);
格子的宽度代表此函数及其子函数所有分配内存的总量。当我们发现某些函数的格子较宽,说明此函数分配的内存较多。如果某些函数分配内存较多但是其子函数分配却并不多(如下图,火焰图中存在较宽的栈顶,即 plateaus),说明此函数自身可能存在大量分配操作;
火焰图中每个格子的颜色是随机的。
在浏览器中打开火焰图的 SVG 文件可以交互式地点击进入每个函数进行更加具体的分析。
Jemalloc 返回的堆内存详情包含了调用栈各个函数的地址,在生成火焰图时需要将地址翻译成文件名和行号,而这正是耗时最长的步骤。通常在 Linux 系统下,这项工作是由 GNU Binutils[9] 中的 addr2line 工具完成的。为了加快火焰图生成的速度,我们可以用 glimi-rs/addr2line[10] 来替换 Binutils 的 addr2line 工具,从而可以获得至少 1 倍的速度提升。
git clone https://github.com/gimli-rs/addr2line
cd addr2line
cargo build --release
sudo cp /usr/bin/addr2line /usr/bin/addr2line-bak
sudo cp target/release/examples/addr2line /usr/bin/addr2line
在常见的内存泄漏场景中,内存的使用量往往是缓慢增长的。因此我们在内存增长的过程中,分别截取两个时间点的内存使用情况,两者之差往往指示着可能出现内存泄漏的地方。
curl -s <greptimedb_ip>:4000/v1/prof/mem > base.hprof
curl -s <greptimedb_ip>:4000/v1/prof/mem > leak.hprof
jeprof <path_to_greptime_binary> --base ./base.hprof ./leak.hprof --collapse | flamegraph.pl > leak.svg
在使用 --base 参数指定基准生成的火焰图中,只会包含本次采集内存分配和基准之间的内存差值的分配情况,从而能够更加清晰地看到内存使用量的增长到底是由哪些函数调用产生的。
[1] https://github.com/GreptimeTeam/greptimedb/pull/1733
[2] https://github.com/jemalloc/jemalloc
[3] https://greptime.com/blogs/2023-06-15-rust-memory-leaks
[4] https://www.brendangregg.com/flamegraphs.html
[5] https://www.brendangregg.com/
[6] https://pkgs.org/search/?q=jeprof&on=files
[7] https://github.com/GreptimeTeam/greptimedb/issues/3166
[8] https://jemalloc.net/jemalloc.3.html#heap_profile_format
[9] https://www.gnu.org/software/binutils/
[10] https://github.com/gimli-rs/addr2line
如果你有任何疑问或建议,欢迎扫描下方小助手微信私聊我们~
关于 Greptime
Greptime 格睿科技于 2022 年创立,目前正在完善和打造时序数据库 GreptimeDB,格睿云 GreptimeCloud 和可观测工具 GreptimeAI 这三款产品。
GreptimeDB 是一款用 Rust 语言编写的时序数据库,具有分布式、开源、云原生、兼容性强等特点,帮助企业实时读写、处理和分析时序数据的同时,降低长期存储的成本。
GreptimeCloud 基于开源的 GreptimeDB,为用户提供全托管的 DBaaS,能够与可观测性、物联网等领域结合的应用产品结合。利用云提供软件和服务,可以达到快速的自助开通和交付,标准化的运维支持,和更好的资源弹性。
GreptimeAI 是为 LLM 应用量身定制的可观测性解决方案,开发者可以通过该方案全面、深入地了解应用的成本、性能、流量和安全情况,在保证低成本和高性能的同时提供高效可靠的分析能力,同时保留了时序数据库的灵活性。
GreptimeCloud 已正式公测,欢迎关注公众号或官网了解最新动态!
官网:https://greptime.cn/
GitHub: https://github.com/GreptimeTeam/greptimedb
文档:https://docs.greptime.cn/
Twitter: https://twitter.com/Greptime
Slack: https://greptime.com/slack
LinkedIn: https://www.linkedin.com/company/greptime/
往期精彩文章:
GreptimeDB 提供 Enterprise 企业版服务,如有需要请联系 info@greptime.com 或添加小助手微信(微信号:greptime).
👇 点击下方阅读原文,立即体验 GreptimeDB!