文章目录
- 1. Heaptrack是什么
- 2. Heaptrack有哪些功能
- 3. Heaptrack和valgrind massif对比
- 4. Heaptrack安装
- 5. Heaptrack生成追踪文件
- 6. heaptrack_gui进行内存分析
- 7. heaptrack_print也能用于堆分析
- 8. 报错解决
- 9. 补充介绍:heaptrack编译安装
1. Heaptrack是什么
- heaptrack是一个linux堆内存分析器, 可以分为两个工具: 用于数据收集的heaptrack + 用于可视化显示的heaptrack_gui. 两者可以独立构建, 但版本需要配套
- heaptrack包含5个部分:
- libheaptrack_proad.so:使用LD_preload技巧注入被调试应用程序的共享库。可以获取原始指令指针的回溯, 触发共享库上运行时信息的收集, 通过计时器了解实时的内存分配和消耗.
- libheaptrack_inject.so:与preload variant类似,此库用于对现有进程的运行时附着(runtime-attachment)。其他内存分析工具不能执行运行时附着
- heaptrack_interpret:通过stdin读取libheaptrack.so的输出,并在libbacktrace的帮助下用DWARF调试符号注释指令指针地址。带注释的数据流被发送到stdout并输出为gzip压缩格式以节省磁盘空间
- heaptrack:结合了前两个工具的脚本, 将传递参数作为具有正确LD_PRELOAD环境的进程来启动.
- heaptrack_print:此过程分析heaptracke_interpret的输出。支持对heaptrack输出gzip文件的透明解压缩
2. Heaptrack有哪些功能
- heaptrack能做的事情:
- 跟valgrind massif一样能分析堆内存消耗
- 呈现分配函数的调用次数: 提供像valgrind callgraph的探查器
- 查找泄露内存: heaptrack可以快速查看被调试对象停止时哪些内存没有被释放
- 分配内存的大小与调用次数直方图
3. Heaptrack和valgrind massif对比
-
valgrind massif提供了堆分析功能, 但存在以下问题
- 运行速度慢: 尤其是在多线层应用程序上. valgrind是序列化代码执行, 因此开销很大
- 不容易使用: massif通常需要寻找各种合适参数以进行使用, --depth、–detailed freq和–max等等, 生成的数据也偏粗糙
- 结束时才输出: massif要在调试对象结束时才输出数据, 而定期检查输出数据很多时候是很有用的
-
此外, gperftools也有类似heaptrack的功能, 但不能提供heaptrack那么多的数据, 也没有那么高效.
4. Heaptrack安装
-
方式一: 命令安装
sudo apt-get install heaptrack sudo apt-get install heaptrack-guiheaptrack -v # 查看版本号
-
方式二: 编译安装 (最后补充介绍)
5. Heaptrack生成追踪文件
按照github官网的说法, heaptrack可以通过如下方式使用:
-
heaptrack <your application and its parameters>
touch main.cpp vim main.cpp # 输入以下测试代码g++ -g -o main main.cpp
#include <stdlib.h> #include <stdio.h>int main() {int *arr = (int *)malloc(sizeof(int) * 10);printf("After allocation %p\n", arr);arr = NULL;return 0; }
heaptrack ./main
或者: heaptrack -o output_file your_application # output_file是输出文件名
可以输入heaptrack --analyze xxx.gz 进行简单分析
-
heaptrack --pid $(pidof <your application>)
-
报错:cannot runtime-attach, you need to set /proc/sys/kernel/yama/ptrace_scope to 0
-
原因:无法在运行时附加到一个进程,因为系统的 ptrace 控制设置阻止了这种操作;
- ptrace 是一种让进程监视和控制另一个进程的 Linux 系统调用。出于安全考虑,Linux 引入了 ptrace scope 功能,通过写入 /proc/sys/kernel/yama/ptrace_scope 文件来控制。当这个值不是 0 时,非root用户不能ptrace附加到除其子进程以外的任何进程,以防止未授权的用户修改或者获取敏感信息;
-
解决:echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
-
但是会降低系统的安全性,应谨慎操作
-
解决后再次执行命令, 可以看到在特定目录下会生成追踪文件
-
heaptrack会引起额外的性能开销, 如果执行较大程序, 可能需要等待一会, 如下
-
如果执行太慢,可以尝试更新 libunwind
- 先查看libunwind版本: http://download.savannah.gnu.org/releases/libunwind/
wget http://download.savannah.gnu.org/releases/libunwind/libunwind-1.6.2.tar.gz tar -xf libunwind-1.1.tar.gz cd libunwind-1.1 ./configure make make install
-
6. heaptrack_gui进行内存分析
-
sudo apt-get install heaptrack 会默认安装heaptrack_gui
-
然后执行如下命令分析内存详情
heaptrack_gui xxx.gz # heaptrack生成的.gz文件
-
通过编译源码安装的heaptrack默认没有装heaptrack_gui,可通过文章最后补充介绍部分修改编译选项进行解决
7. heaptrack_print也能用于堆分析
-
待测试,本人未使用过该命令进行堆分析
-
并把结果直接打印出来, 使用方式
heaptrack_print heaptrack.APP.PID.gz | less
-
输出报告包含:
MOST CALLS TO ALLOCATION FUNCTIONS PEAK MEMORY CONSUMERS MOST TEMPORARY ALLOCATIONS
-
每个部分列出前10个热点, 同时使用heaptrack_print还能将heaptrack数据转换为massif数据格式, 然后可以通过flamegraph.pl生成一个折叠的堆栈消耗报告
8. 报错解决
-
Could not attach to process. If your uid matches the uid of the target process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try again as the root user. For more details, see /etc/sysctl.d/10-ptrace.conf ptrace: Operation not permitted.
- 原因和解决方法: 权限不够, 使用sudo运行; 不行的话就按照这篇博客https://blog.csdn.net/thesre/article/details/117454665 , 修改/proc/sys/kernel/yama/ptrace_scope为0并生效/etc/sysctl.d/10-ptrace.conf
-
heaptrack --pid $(pidof your_process_name)生成文件格式为.zst并且大小为0
我们在容器内运行程序, 在容器外执行heaptrack, 注意看报错Target and debugger are in different PID namespaces; thread lists and other data are likely unreliable. Connect to gdbserver inside the container. 在不同的PID命名控件, 线程列表和数据不可靠. 用的是docker container里的gdbserver
- 原因和解决方法:在容器外获取到的PID可能和容器内不一致, 此外可能还有内存权限的问题, 需要在容器内执行heaptrack --pid命令
-
容器内heaptrack生成的数据文件无法在容器外heaptrack_gui访问
- 原因: heaptrack_gui版本过低
- 解决: 升级heaptrack_gui版本, 源码编译的时候使用cmake … -DBUILD_GUI=ON编译选项构建带图形界面的版本, 即heaptrack_gui
9. 补充介绍:heaptrack编译安装
-
[这种方式需要单独安装heaptrack_gui, 可能存在版本不配套的问题]
-
按照github或者gitee安装指引操作:
cd heaptrack # i.e. the source folder mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release .. #look for messages about missing dependencies! make -j$(nproc)
-
cmake -DCMAKE_BUILD_TYPE=Release … 报错:
-
报错1:Could NOT find Libunwind(missing: LIBUNWIND_INCLUDE_DIR LIBUNWIND_LIBRARY LIBUNWIND_HAS_UNW_BACKTRACE)
-
解决方法:安装libunwind8-dev之后解决: sudo apt-get install libunwind8-dev
- (sudo apt-get install -y libunwind-dev安装最新版?)
-
报错2:Could NOT find Elfutils (missing: LIBDW_LIBRARIES LIBDW_INCLUDE_DIR) (Required is at least version “0.158”)
-
解决方法:
sudo apt-get -y install elfutils # 安装后仍报错 # 下载源码切换到大于0.158版本的tag后编译安装: git clone git://sourceware.org/git/elfutils.git git tag git checkout -b dev_elfutils-0.159 elfutils-0.159 # 软件准备 apt-get install autoconf apt-get install autopoint apt-get install flex bison # cat README # 查看README 按指导进行编译 autoreconf -i -f sudo apt-get install gawk ./configure --enable-maintainer-mode --disable-debuginfod make make check sudo make install
-
make check执行完之后
-
补充: GNU elfutils是一个开源的工具集,用于处理ELF(Executable and Linkable Format)格式的可执行文件、目标文件和共享库 elfutils工具
-
报错3:warning 3: Could NOT find ECM (missing: ECM_DIR)
sudo apt-get install extra-cmake-modules # 因为只是warning, 安装不成功好像也不影响make -j$(nproc) #完成编译, 如下
-
再执行sudo make install后完成安装
-
heaptrack -v查看版本信息
-
补充:通过编译源码安装的heaptrack默认没有装heaptrack_gui?
- 不推荐使用源码编译安装heaptrack, 源码编译默认没有安装heaptrack_gui, 通过sudo apt-get install heaptrack也没有默认安装heaptrack_gui, 需要单独安装, 安装命令如下:
# sudo apt install heaptrack-gui #命令安装可能不配套cd build; cmake .. -DBUILD_GUI=ON # 编译时安装需要运行命令
-
创作不易,如有帮助,请点赞收藏支持
[参考文章]
[1]. Heaptrack - A Heap Memory Profiler For Linux, 重点参考, 和valgrind massif的区别等
[2]. Linux Ubuntu上如何安装libunwind
[3]. sudo apt-get -y install elfutils
[4]. elfutils编译问题记录
[5]. 编译eflutils方法
[6]. heaptrack检测是否存在内存泄露
[7]. heaptrack无法检测到内存泄露例子
[8]. ubuntu20.04安装heaptrack
[9]. heaptrack和valgrind/massif的区别
[10]. heaptrack github官网
created by shuaixio, 2024.04.09