gperftools是google开发的一款非常实用的工具集,主要包括:
1.性能优异的malloc free内存分配器tcmalloc;
2.基于tcmalloc的堆内存检测和内存泄漏分析工具heap-profiler,heap-checker;
3.基于tcmalloc实现的程序CPU性能监测工具cpu-profiler.
本文主要讲述profiler在CPU性能分析方面的使用
CPU profiler的使用方式类似heap-profiler,区别就是要在构建你的程序时不仅要链接-ltcmalloc还要链接-lprofiler。它也是需要一个函数调用(ProfilerStart)来开启,和一个函数调用(ProfilerStop)来关闭,调用这些函数需要include
% pprof /bin/ls ls.prof
Enters “interactive” mode
% pprof –text /bin/ls ls.prof
Outputs one line per procedure
% pprof –gv /bin/ls ls.prof
Displays annotated call-graph via ‘gv’
% pprof –gv –focus=Mutex /bin/ls ls.prof
Restricts to code paths including a .*Mutex.* entry
% pprof –gv –focus=Mutex –ignore=string /bin/ls ls.prof
Code paths including Mutex but not string
% pprof –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:1234
Outputs one line per procedure for localhost:1234
% pprof –callgrind /bin/ls ls.prof
Outputs the call information in callgrind format
我们实践中用的最多的是导出成pdf格式,非常直观,描述文档在此http://google-perftools.googlecode.com/svn/trunk/doc/heapprofile.html,
因为这个有向图代表的意义类似之前在heap-profiler中所描述的图,所以不再多着笔墨。
实践证实CPU profiler效果很好,为我们一次次定位了性能热点,为此让人好奇其实现原理。
CPU profiler的原理类似许多其他proflier,都是对运行着的程序定时采样,最后根据每次记录的堆栈频度导出采样信息。
网上有人这样解释到:相当于用gdb attach一个正在运行的进程,然后每隔一段时间中断程序打印堆栈,当然耗时最多的调用最频繁的堆栈是最常被打印出来的。
有稍微看过gperftools这方面的实现,大致就是注册一个定时触发的信号(SIGPROF)处理函数,在此函数中获取当前堆栈信息,通过hash算法以此做hash表的key,放入样本统计hash table中,如果hash table中已经有同样的堆栈key了,value就加1,这样当采样结束,就把hash table的统计信息导出到文件供pprof程序解析,从而得到真正直观的profile信息。
1. 下载 gperftools (wget https://gperftools.googlecode.com/files/gperftools-2.1.tar.gz)
mkdir ../gperftools
./configure prefix=/home/tools/gperftools
make && make install
2. 下载libunwind (wget http://download.savannah.gnu.org/releases/libunwind/libunwind-1.1.tar.gz)
mkdir ../libunwind
./configure prefix=/home/tools/libunwind
make && make install
3. export LD_LIBRARY_PATH=/home/tools/gperftools/lib
export PATH=$PATH:/home/tools/gperftools/bin
===Archlinux替代1-3:pacman -S gperftools
如果需要生成图表 pacman -S graphviz
如果需要生成打印 pacman -S gv
4. mkdir test && cd test
nano -w test.cpp #include#include using namespace std; void test1() { int i = 0; while (i < 1000) { i++; } } void test2() { int i = 0; while (i < 2000) { i++; } } void test3() { for (int i = 0; i < 100000; ++i) { test1(); test2(); } } int main() { ProfilerStart("test.prof"); // test.prof is the name of profile file test3(); cout<<"Finish!"< 5. 编译
编译版本:
g++ -o test test.cpp -I /home/tools/gperftools/include -I /home/tools/libunwind/include -L/home/tools/gperftools/lib/ -lprofiler -L/home/tools/libunwind/lib/ -lunwind
安装版本:
g++ -o test test.cpp -lprofiler -lunwind
6. 生成test.prof文件[root@nasSrv test]# ./test Finish! PROFILE: interrupts/evictions/bytes = 133/6/5447. pprof --text test test.prof
输出:Using local file test. Using local file test.prof. Total: 133 samples 74 55.6% 55.6% 74 55.6% test2 59 44.4% 100.0% 59 44.4% test1 0 0.0% 100.0% 133 100.0% __libc_start_main 0 0.0% 100.0% 133 100.0% main 0 0.0% 100.0% 133 100.0% test3