c++分析gperftools总结
习惯了golang的net/http/pprof的便利,c++的性能分析就显得繁琐了一点。
不过大致上还是一致的。
安装
包管理安装
1 | centos: |
64位系统还需要安装unwind(google-perftools出现的时候64位还没普及,现在libunwind应该是必装了)
1 | centos: |
这样就完毕了,简单的很,但是后面在装http接口支持库的时候会缺失一个stacktrace库。
我给出了一个现成的stacktrace静态库,但是如果遇到兼容性问题只能自己通过源码安装来解决。
没遇到兼容性问题的时候可以忽略下面的源码安装步骤
源码安装
先装libunwind
1 | wget http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-beta.tar.gz |
再装google-perftools
1 | wget http://google-perftools.googlecode.com/files/google-perftools-1.6.tar.gz |
使用
编译选项
1 | TARGET_LINK_LIBRARIES(${TARGET} tcmalloc) |
cpu profile
cpu使用检测
https://gperftools.github.io/gperftools/cpuprofile.html
1 | //SIGUSR1: start profiling |
对SIGUSR1和SIGUSR2注册信号来进行调优开始和结束
运行后使用pprof看结果
--lines
按行统计
--func
按函数统计
1 | #文本结果 |
heap profile
内存使用检测
https://gperftools.github.io/gperftools/heapprofile.html
1 | <gperftools/heap-profiler.h> |
会输出很多个profile.000x.heap文件
如果发现没有输出,可能是内存使用太少了,参数HEAP_PROFILE_ALLOCATION_INTERVAL控制多少内存使用dump一次
默认是1073741824 (1 Gb)
对输出的out.exe使用如下命令来对比出结果
1 | pprof --base=/tmp/profile.0004.heap out.exe /tmp/profile.0100.heap |
heap checker
内存泄露检测
1 | HeapLeakChecker heap_checker("test_foo"); |
执行完毕以后使用HEAPCHECK=local ./out.exe
或者更严格的HEAPCHECK=draconian ./out.exe
来检测泄露
如果存在泄漏的话,会assert停掉,并且提示你运行命令去跑pprof看泄漏点,例如
1 | Leak of 4 bytes in 1 objects allocated from: |
如果是ubuntu20的话,pprof命令变成了google-pprof,这个挺坑的
要注意活动对象检测问题,local模式没问题以后最好在用draconian跑一次看看
“活动对象”检测:在程序执行的任意时刻,所有可访问的内存都被认为是活动的对象。这包括所有的全局变量以及全局指针变量指向的内存,所有从当前stack frame及CPU寄存器可达的所有内存,还包括线程本地存储、thread heaps、以及从线程本地存储、thread heaps可达的内存空间。对于除“draconian”之外的所有模式来说,活动对象都不会被视为是内存泄露。
不推荐直接使用gooogle-perftools
这和golang直接使用http接口来进行性能分析比麻烦了很多,万幸的是google也提供了http接口的支持
配合http接口体验更好
http接口安装
库名是gperftools-httpd,包管理没有,必须进行源码安装
google code因为已经被google放弃了,因此不能下载了,github有个可以用的
1 | git clone https://github.com/awesomeleo/gperftools-httpd |
直接使用会遇到一些问题
这里有个我fork的库,已经完成了下面步骤一。在centos 6下可以和包管理的gperftools一起使用,但并不保证你一定可用
如果不可用需要自己重复步骤一
步骤一 配置
这是个c的库,c++要使用的话需要修改gperftools-httpd.h
1 | extern "C" { |
然后编译的时候会报错找不到libstacktrace
libstacktrace是只有gperftools在源码编译以后,在编译结果的目录里才能找到的
1 | cp gperftools/.libs/libstacktrace.a gperftools-httpd |
记得修改Makefile去当前目录找库
步骤二 安装
1 | cd gperftools-httpd |
http接口使用
1 | #include <iostream> |
1 | g++ -g -O0 -o main gperftool-test.cpp -lghttpd -lprofiler -lpthread |
使用http接口查看
1 | [root@localhost.localdomain ~]# pprof ./main http://localhost:9999/pprof/profile |
使用可能遇到的问题
运行时出现:No nodes to print
程序逻辑使用CPU次数太少,无法分析
运行时出现:SIGPROF handler is already in use
使用了其它的性能分析工具如:gprof等,造成冲突
pg选项
要注意有没有带pg选项,由于和gprof是冲突的,带了pg选项会无法使用
静态编译后性能变差
大约性能会下降10-20倍
根据gperftools文档
INSTALL document to fix hung bug of libunwind
CAUTION: if you install libunwind from the url above, be aware that you may have trouble if you try to statically link your binary with perftools: that is, if you link with 'gcc -static -lgcc_eh ...'. This is because both libunwind and libgcc implement the same C++ exception handling APIs, but they implement them differently on some platforms. This is not likely to be a problem on ia64, but may be on x86-64.
Also, if you link binaries statically, make sure that you add -Wl,--eh-frame-hdr to your linker options. This is required so that libunwind can find the information generated by the compiler required for stack unwinding.
Using -static is rare, though, so unless you know this will affect you it probably won't.
纯静态链接-static
需要添加-Wl,--eh-frame-hdr
选项
总结
简单探究了如何使用google-perftools工具配合http接口查看cpu分析结果
后续遇到问题还会继续更新
参考资料
-
2024-05-01
最近实在太忙啦,好几个月没写博客了,趁着五一放假补一篇
最近运维同学调整了告警策略,将连续coredump才告警,改成了每次coredump必告警
业务部门顿时向我报障了taf框架的coredump
一开始core在了tcmalloc,因为tcmalloc不会第一时间coredump,所以内存问题会跑一段时间才出现