【linux性能分析】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-gui
    
    heaptrack -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 … 报错:

    • 报错1Could 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安装最新版?)
    • 报错2Could 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工具

    • 报错3warning 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值