文章目錄
- 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