日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【程序性能分析利器】Google Perf Tool 和 Valgrind 工具包简介

發布時間:2025/3/15 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【程序性能分析利器】Google Perf Tool 和 Valgrind 工具包简介 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Google Perf Tools 的安裝和使用

?

  • Gperf 工具包包含如下幾個工具:
    • 一個優化的內存管理算法—tcmalloc性能優于malloc。
    • 一個用于CPU profile的工具,用于檢測程序的性能熱點,這個功能和gprof類似。
    • 一個用于堆檢查工具,用于檢測程序在是夠有內存泄露,這個功能和valgrind類似。
    • 一個用于Heap profile的工具,用于監控程序在執行過程的內存使用情況。
  • 其使用方法如下:
1.使用其提供的內存管理函數---TC Malloc:gcc [...] -ltcmalloc 2.使用其堆內存檢查工具---Heap Checker:gcc [...] -o myprogram -ltcmallocHEAPCHECK=normal ./myprogram 3.使用Heap Profiler:gcc [...] -o myprogram -ltcmallocHEAPPROFILE=/tmp/netheap ./myprogram 4.使用Cpu Profiler:gcc [...] -o myprogram -lprofilerCPUPROFILE=/tmp/profile ./myprogram

官方代碼:https://github.com/gperftools/gperftools
官方文檔:?http://code.google.com/p/google-perftools/wiki/GooglePerformanceTools
官方 github 簡要文檔:https://gperftools.github.io/gperftools

?

1.安裝依賴 libunwind

(1)源碼安裝libunwind

wget https://github.com/libunwind/libunwind/archive/v0.99.tar.gz tar -xvf v0.99.tar.gz cd libunwind-0.99 autoreconf --force -v --install ./configure make make install

其安裝版本可自行選擇。在 ./configure 步如果不加生成選項,--prefix=path 不指定安裝的目錄, lib 會默認產生在系統/usr/local/lib,頭文件在 /usr/local/include

?

(2)yum安裝

yum search libunwind # 查找,然后選擇需要的安裝 yum install libunwind-devel.x86_64

?

2.安裝gperftools

源碼安裝google-perf-tools/gperftools

wget https://github.com/gperftools/gperftools/releases/download/gperftools-2.6.1/gperftools-2.6.1.tar.gz tar -xvf gperftools-2.6.1.tar.gz # 解壓 ./configure --prefix=gperftools-tutorial/output make make install

2.1 問題

問題一:安裝時可能出現configure: WARNING: No frame pointers and no libunwind. Using experimental backtrace capturing via libgcc.Expect crashy cpu profiler。
是因為沒有安裝libunwind。在gperftools工具的INSTLL例有說明,64位系統需要安裝。使用yum search libunwind查找,然后選擇需要的安裝。

問題二:編譯時打開了./configure –enable-frame-pointers ,這要求被測試的程序在編譯時要加上gcc編譯選項,否則某些多線程程序可能會 core:CCFLAGS=-fno-omit-frame-pointer

?

3.gperftools使用

我們在Google使用的CPU分析器。使用它的過程分為三個部分:將庫鏈接到應用程序,運行代碼以及分析輸出。

3.1? Linking in the Library

要將CPU profiler安裝到可執行文件中,請添加-lprofiler鏈接到可執行文件。(也可能在運行時使用LD_PRELOAD,例如 在添加 % env LD_PRELOAD="/usr/lib/libprofiler.so"

(1)如果是默認的prefix安裝在/usr/local/lib/libprofiler.so

g++ src/test-normal/test-normal.cpp -lprofiler -o test-normal

(2)按順序執行下列shell

export LD_PRELOAD="/usr/local/lib/libprofiler.so" g++ src/test-normal/test-normal.cpp -o test-normal env CPUPROFILE=test-normal.prof ./test-normal

可以看到profiler的文件test-normal.prof

(3)

env LD_PRELOAD=/usr/local/lib/libprofiler.so CPUPROFILE=test-normal.prof ./test-normal

可以看到profiler的文件test-normal.prof

?

3.2 Running the Code

此外,還可以將其嵌入到代碼中運行。此處可參考官方文檔。

3.3 Analyzing the Output

需要dot為任何圖形輸出,yum install graphviz, 這里有一些調用pprof的方法。這些將在下面更詳細地描述。

pprof /bin/ls ls.profEnters "interactive" modepprof --text /bin/ls ls.profOutputs one line per procedurepprof --gv /bin/ls ls.profDisplays annotated call-graph via 'gv'pprof --gv --focus=Mutex /bin/ls ls.profRestricts to code paths including a .*Mutex.* entrypprof --gv --focus=Mutex --ignore=string /bin/ls ls.profCode paths including Mutex but not stringpprof --list=getdir /bin/ls ls.prof(Per-line) annotated source listing for getdir()pprof --disasm=getdir /bin/ls ls.prof(Per-PC) annotated disassembly for getdir()pprof --text localhost:1234Outputs one line per procedure for localhost:1234pprof --callgrind /bin/ls ls.profOutputs the call information in callgrind format pprof --pdf test-server test-server.prof > test-server.pdf

(1)節點信息

查看 test-server.pdf,在pprof的各種圖形模式中,輸出是帶有時序信息注釋的調用圖每個節點代表一個過程。有向邊指示調用者與被調用者的關系。每個節點的格式如下表所示。

最后一兩行包含時序信息。(分析是通過采樣方法完成的,默認情況下,我們每秒進行100次采樣。因此,輸出中的一個時間單位對應于大約10毫秒的執行時間。)"local"時間是執行指令所花費的時間。直接包含在過程中(以及該過程中內聯的任何其他過程中)。“cumulative”時間是“local”時間與在任何被調者身上花費的時間之和。如果累計時間與當地時間相同,則不會打印。

字段名描述
Class Name類名,非類成員函數此項為空
Method Name函數名
local (percentage)當前函數直接執行的指令所消耗的CPU時間(包括內聯函數)(百分比)
of cumulative (percentage)當前函數的local時間及其調用的函數的local時間總和(百分比),如果與local相同,則不顯示

(2)邊信息

從一個節點到另一個節點的邊表示調用者與被調用者的關系。每個邊都標有被調用者代表調用者花費的時間。
有向邊:調用者指向被調用者,有向邊上的時間表示被調用者所消耗的CPU時間

?

valgrind的callgrind工具進行多線程性能分析


安裝

1.http://valgrind.org/downloads/old.html2.yum install valgrind3. 上述安裝完 gperf 后便會默認安裝 valgrind 工具包。

Valgrind 的主要作者 Julian Seward 剛獲得了今年的Google-O'Reilly開源大獎之一──Best Tool Maker。讓我們一起來看一下他的作品。Valgrind 是運行在 Linux 上一套基于仿真技術的程序調試和分析工具,它包含一個內核──一個軟件合成的CPU,和一系列的小工具,每個工具都可以完成一項任務──調試,分析,或測試等。Valgrind可以檢測內存泄漏和內存違例,還可以分析cache的使用等,靈活輕巧而又強大,能直穿程序錯誤的心臟,真可謂是程序員的瑞士軍刀。?

一. Valgrind概觀?


Valgrind的最新版是3.2.0,它一般包含下列工具:?
?

1.Memcheck?

最常用的工具,用來檢測程序中出現的內存問題,所有對內存的讀寫都會被檢測到,一切對malloc()/free()/new/delete的調用都會被捕獲。所以,它能檢測以下問題:?
1.對未初始化內存的使用;?
2.讀/寫釋放后的內存塊;?
3.讀/寫超出malloc分配的內存塊;?
4.讀/寫不適當的棧中內存塊;?
5.內存泄漏,指向一塊內存的指針永遠丟失;?
6.不正確的malloc/free或new/delete匹配;?
7,memcpy()相關函數中的dst和src指針重疊。?
這些問題往往是C/C++程序員最頭疼的問題,Memcheck在這里幫上了大忙。?

2.Callgrind?

和gprof類似的分析工具,但它對程序的運行觀察更是入微,能給我們提供更多的信息。和gprof不同,它不需要在編譯源代碼時附加特殊選項,但加上調試選項是推薦的。Callgrind收集程序運行時的一些數據,建立函數調用關系圖,還可以有選擇地進行cache模擬。在運行結束時,它會把分析數據寫入一個文件。callgrind_annotate可以把這個文件的內容轉化成可讀的形式。?

3.Cachegrind?

Cache分析器,它模擬CPU中的一級緩存I1,Dl和二級緩存,能夠精確地指出程序中cache的丟失和命中。如果需要,它還能夠為我們提供cache丟失次數,內存引用次數,以及每行代碼,每個函數,每個模塊,整個程序產生的指令數。這對優化程序有很大的幫助。?

4.Helgrind?


它主要用來檢查多線程程序中出現的競爭問題。Helgrind尋找內存中被多個線程訪問,而又沒有一貫加鎖的區域,這些區域往往是線程之間失去同步的地方,而且會導致難以發掘的錯誤。Helgrind實現了名為“Eraser”的競爭檢測算法,并做了進一步改進,減少了報告錯誤的次數。不過,Helgrind仍然處于實驗階段。?

5. Massif?

堆棧分析器,它能測量程序在堆棧中使用了多少內存,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少內存的使用,在帶有虛擬內存的現代系統中,它還能夠加速我們程序的運行,減少程序停留在交換區中的幾率。?
此外,lackey和nulgrind也會提供。Lackey是小型工具,很少用到;Nulgrind只是為開發者展示如何創建一個工具。我們就不做介紹了。?

二. 使用Valgrind?


Valgrind的使用非常簡單,valgrind命令的格式如下:?

valgrind [valgrind-options] your-prog [your-prog options]?


一些常用的選項如下:?
選項? :作用?
-h --help? ? ? 顯示幫助信息。?
--version? ? ?顯示valgrind內核的版本,每個工具都有各自的版本。?
-q --quiet? ? ?安靜地運行,只打印錯誤信息。?
-v --verbose? ?打印更詳細的信息。?
--tool= [default: memcheck]? ? 最常用的選項。運行valgrind中名為toolname的工具。如果省略工具名,默認運行memcheck。?
--db-attach= [default: no]? ? ?綁定到調試器上,便于調試錯誤。?

我們通過例子看一下它的具體使用。我們構造一個存在內存泄漏的C程序,如下:??

#include #include void f(void) { int* x = malloc(10 * sizeof(int)); x[10] = 0; // problem 1: heap block overrun } // problem 2: memory leak -- x not freed int main(void) { int i; f(); printf("i=%d/n",i); //problem 3: use uninitialised value. return 0; }

保存為memleak.c并編譯,然后用valgrind檢測。?

$ gcc -Wall -o memleak memleak.c?
$ valgrind --tool=memcheck ./memleak?

我們得到如下錯誤信息: ==3649== Invalid write of size 4 ==3649== at 0x80483CF: f (in /home/wangcong/memleak) ==3649== by 0x80483EC: main (in /home/wangcong/memleak) ==3649== Address 0x4024050 is 0 bytes after a block of size 40 alloc'd ==3649== at 0x40051F9: malloc (vg_replace_malloc.c:149) ==3649== by 0x80483C5: f (in /home/wangcong/memleak) ==3649== by 0x80483EC: main (in /home/wangcong/memleak) 前面的3649是程序運行時的進程號。第一行是告訴我們錯誤類型,這里是非法寫入。下面的是告訴我們錯誤發生的位置,在main()調用的f()函數中。 ==3649== Use of uninitialised value of size 4 ==3649== at 0xC3A264: _itoa_word (in /lib/libc-2.4.so) ==3649== by 0xC3E25C: vfprintf (in /lib/libc-2.4.so) ==3649== by 0xC442B6: printf (in /lib/libc-2.4.so) ==3649== by 0x80483FF: main (in /home/wangcong/memleak) 這個錯誤是使用未初始化的值,在main()調用的printf()函數中。這里的函數調用關系是通過堆棧跟蹤的,所以有時會非常多,尤其是當你使用C++的STL時。其它一些錯誤都是由于把未初始化的值傳遞給libc函數而被檢測到。在程序運行結束后,valgrind還給出了一個小的總結: ==3649== ERROR SUMMARY: 20 errors from 6 contexts (suppressed: 12 from 1) ==3649== malloc/free: in use at exit: 40 bytes in 1 blocks. ==3649== malloc/free: 1 allocs, 0 frees, 40 bytes allocated. ==3649== For counts of detected errors, rerun with: -v ==3649== searching for pointers to 1 not-freed blocks. ==3649== checked 47,256 bytes. ==3649== ==3649== LEAK SUMMARY: ==3649== definitely lost: 40 bytes in 1 blocks. ==3649== possibly lost: 0 bytes in 0 blocks. ==3649== still reachable: 0 bytes in 0 blocks. ==3649== suppressed: 0 bytes in 0 blocks. ==3649== Use --leak-check=full to see details of leaked memory.

我們可以很清楚地看出,分配和釋放了多少內存,有多少內存泄漏。這對我們查找內存泄漏十分方便。然后我們重新編譯程序并綁定調試器:?

$ gcc -Wall -ggdb -o memleak memleak.c?
$ valgrind --db-attach=yes --tool=memcheck ./memleak?


一出現錯誤,valgrind會自動啟動調試器(一般是gdb):

==3893== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- y? starting debugger? ==3893== starting debugger with cmd: /usr/bin/gdb -nw /proc/3895/fd/1014 3895?


退出gdb后我們又能回到valgrind繼續執行程序。?
還是用上面的程序,我們使用callgrind來分析一下它的效率:?

$ valgrind --tool=callgrind ./memleak?


Callgrind會輸出很多,而且最后在當前目錄下生成一個文件: callgrind.out.pid。用callgrind_annotate來查看它:?

$ callgrind_annotate callgrind.out.3949?


詳細的信息就列出來了。而且,當callgrind運行你的程序時,你還可以使用callgrind_control來觀察程序的執行,而且不會干擾它的運行。?
再來看一下cachegrind的表現:?

$ valgrind --tool=cachegrind ./memleak?
得到如下信息:?

==4073== I refs: 147,500 ==4073== I1 misses: 1,189 ==4073== L2i misses: 679 ==4073== I1 miss rate: 0.80% ==4073== L2i miss rate: 0.46% ==4073== ==4073== D refs: 61,920 (46,126 rd + 15,794 wr) ==4073== D1 misses: 1,759 ( 1,545 rd + 214 wr) ==4073== L2d misses: 1,241 ( 1,062 rd + 179 wr) ==4073== D1 miss rate: 2.8% ( 3.3% + 1.3% ) ==4073== L2d miss rate: 2.0% ( 2.3% + 1.1% ) ==4073== ==4073== L2 refs: 2,948 ( 2,734 rd + 214 wr) ==4073== L2 misses: 1,920 ( 1,741 rd + 179 wr) ==4073== L2 miss rate: 0.9% ( 0.8% + 1.1% )

上面的是指令緩存,I1和L2i緩存,的訪問信息,包括總的訪問次數,丟失次數,丟失率。?
中間的是數據緩存,D1和L2d緩存,的訪問的相關信息,下面的L2緩存單獨的信息。Cachegrind也生成一個文件,名為cachegrind.out.pid,可以通過cg_annotate來讀取。輸出是一個更詳細的列表。Massif的使用和cachegrind類似,不過它也會生成一個名為massif.pid.ps的PostScript文件,里面只有一幅描述堆棧使用狀況的彩圖。?


以上只是簡單的演示了valgrind的使用,更多的信息可以在它附帶的文檔中得到,也可以訪問valgrind的主頁:http://www.valgrind.org。學會正確合理地使用valgrind對于調試程序會有很大的幫助。
?

三、使用valgrind的callgrind工具進行多線程性能分析

valgrind是開源的性能分析利器。 根據它的文檔,可以用它來檢查內存泄漏等問題,還可以用來生成函數的調用圖,就這兩個功能就足夠有吸引力了。

本文主要是介紹如何使用valgrind的callgrind工具進行性能分析。

分析過程

使用callgrind工具生成性能分析數據

命令格式如下:

valgrind --tool=callgrind ./exproxy

其中 ./exproxy就是我們要分析的程序。執行完畢后,就會在當前目錄下生成一個文件。文件名為“callgrind.out.進程號”。如,callgrind.out.31113。注意,對于daemon進程的調試,不要通過kill -9方式停止。

如果你調試的程序是多線程,你也可以在命令行中加一個參數 -separate-threads=yes。這樣就會為每個線程單獨生成一個性能分析文件。如下:

valgrind --tool=callgrind --separate-threads=yes ./exproxy

生成的文件除了callgrind.out.31113外,還會多出一些子線程的文件。文件名如下:

callgrind.out.31113-01 ? ?callgrind.out.31113-02 ? ?callgrind.out.31113-03

把callgrind生成的性能數據轉換成dot格式數據

可以使用gprof2dot.py腳本,把callgrind生成的性能分析數據轉換成dot格式的數據。方便使用dot把分析數據圖形化。

腳本可以?點此下載?。腳本使用方式如下:

python gprof2dot.py -f callgrind -n10 -s callgrind.out.31113 > valgrind.dot

使用dot把數據生成圖片

命令格式如下:

dot -Tpng valgrind.dot -o valgrind.png

生成的圖片示例

通過圖形,我們可以很直觀的知道那段程序執行慢,并且了解相關調用關系。

[root@localhost blake]# cat kk.c#include <stdio.h> #include <stdlib.h>void f1() {int i;int *p;for (i = 0; i < 10; i++) {p = malloc(sizeof(int));*p = 10;free(p);} }void f2() {int i;int *p;for (i = 0; i < 20; i++) {p = malloc(sizeof(int));*p = 10;free(p);} }void f3() {int i;int *p;for (i = 0; i < 30; i++) {p = malloc(sizeof(int));*p = 10;free(p);} }int main() {int i;for (i = 0; i < 1000; i++) {f1();f2();f3();}return 0; }[root@localhost blake]# gcc -g kk.c -okk [root@localhost uu]# valgrind --tool=callgrind ./kk --dump-instr=yes --trace-jump=yes ==4798== Callgrind, a call-graph generating cache profiler ==4798== Copyright (C) 2002-2009, and GNU GPL'd, by Josef Weidendorfer et al. ==4798== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info ==4798== Command: ./kk --dump-instr=yes --trace-jump=yes ==4798== ==4798== For interactive control, run 'callgrind_control -h'. ==4798== ==4798== Events : Ir ==4798== Collected : 11648419 ==4798== ==4798== I refs: 11,648,419 [root@localhost uu]# ll 總用量 44 -rw------- 1 root root 26499 Jul 4 21:01 callgrind.out.4798 -rwxr-xr-x 1 root root 9289 Jul 4 20:48 kk -rw-r--r-- 1 root root 516 Jul 4 20:48 kk.c

把callgrind.out.4798傳到 window 7 ,

如果要時行源代碼顯示,KK.C也傳到windows 7 。

用kcachegrind 打開callgrind.out.4798 ,即顯示下面圖

?

LINUX: http://kcachegrind.sourceforge.net/html/Home.html
windows: https://sourceforge.net/projects/precompiledbin/files/?source=navbar?

其他相關使用介紹的文章可參見:

https://blog.csdn.net/swartz_lubel/category_6968911.html

https://blog.csdn.net/yutianzuijin/article/details/109731052

總結

以上是生活随笔為你收集整理的【程序性能分析利器】Google Perf Tool 和 Valgrind 工具包简介的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。