c++性能分析gperftools总结

原创内容,转载请注明出处

Posted by Weakyon Blog on August 16, 2018

习惯了golang的net/http/pprof的便利,c++的性能分析就显得繁琐了一点。

不过大致上还是一致的。

安装

包管理安装

yum install google-perftools
yum install google-perftools-devel

64位系统还需要安装unwind(google-perftools出现的时候64位还没普及,现在libunwind应该是必装了)

yum install libunwind

这样就完毕了,简单的很,但是后面在装http接口支持库的时候会缺失一个stacktrace库。

我给出了一个现成的stacktrace静态库,但是如果遇到兼容性问题只能自己通过源码安装来解决。

没遇到兼容性问题的时候可以忽略下面的源码安装步骤

源码安装

先装libunwind

wget http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-beta.tar.gz
tar xzvf libunwind-0.99-beta.tar.gz
cd libunwind-0.99-beta
autoreconf -i
./configure
make
make install

再装google-perftools

wget http://google-perftools.googlecode.com/files/google-perftools-1.6.tar.gz
tar xzvf google-perftools-1.6.tar.gz
cd google-perftools-1.6
./autogen.sh
./configure(装完有问题用./confgiure --enable-frame-pointers, google-perftools的INSTALL里这么写的)
make
make install

使用

cmake:

TARGET_LINK_LIBRARIES(${TARGET} profiler)
TARGET_LINK_LIBRARIES(${TARGET} unwind)
TARGET_LINK_LIBRARIES(${TARGET} -Wl,--eh-frame-hdr)

特别要注意有没有带pg选项,由于和gprof是冲突的,带了pg选项会无法使用

code:

//SIGUSR1: start profiling
//SIGUSR2: stop profiling

static void gprof_callback(int signum) {
    if (signum == SIGUSR1) {
        printf("Catch the signal ProfilerStart\n");
        ProfilerStart("bs.prof");
    }
    else if (signum == SIGUSR2) {
        printf("Catch the signal ProfilerStop\n");
        ProfilerStop();
    }
}

static void setup_signal() {
    struct sigaction profstat;
    profstat.sa_handler = gprof_callback;
    profstat.sa_flags = 0;
    sigemptyset(&profstat.sa_mask);
    sigaddset(&profstat.sa_mask, SIGUSR1);
    sigaddset(&profstat.sa_mask, SIGUSR2);

    if (sigaction(SIGUSR1, &profstat,NULL) < 0)
        fprintf(stderr, "SIGUSR1 Fail !");

    if (sigaction(SIGUSR2, &profstat,NULL) < 0)
        fprintf(stderr, "SIGUSR2 Fail !");
}

int main() {
    setup_signal();
    ...
}

对SIGUSR1和SIGUSR2注册信号来进行调优开始和结束

不推荐直接使用gooogle-perftools

这和golang直接使用http接口来进行性能分析比麻烦了很多,万幸的是google也提供了http接口的支持

配合http接口体验更好

http接口安装

库名是gperftools-httpd,包管理没有,必须进行源码安装

google code因为已经被google放弃了,因此不能下载了,github有个可以用的

git clone https://github.com/awesomeleo/gperftools-httpd

直接使用会遇到一些问题

这里有个我fork的库,已经完成了下面步骤一。在centos 6下可以和包管理的gperftools一起使用,但并不保证你一定可用

gperftools-httpd

如果不可用需要自己重复步骤一

步骤一 配置

这是个c的库,c++要使用的话需要修改gperftools-httpd.h

extern "C" {
extern void ghttpd(void);
}

然后编译的时候会报错找不到libstacktrace

libstacktrace是只有gperftools在源码编译以后,在编译结果的目录里才能找到的

cp gperftools/.libs/libstacktrace.a gperftools-httpd

记得修改Makefile去当前目录找库

步骤二 安装

cd gperftools-httpd
make
make install

http接口使用

#include <iostream>
#include "gperftools-httpd.h"

using namespace std;

int main(int argc,char** argv)
{
    ghttpd();
    int i;
    while(1) i++;
}
g++ -g -O0 -o  main gperftool-test.cpp -lghttpd -lprofiler -lpthread
./main

使用http接口查看

[root@localhost.localdomain ~]# pprof  ./main  http://localhost:9999/pprof/profile
Using local file ./main.
Gathering CPU profile from http://localhost:9999/pprof/profile?seconds=30 for 30 seconds to
  /root/pprof/main.1534407852.localhost
Be patient...
Wrote profile to /root/pprof/main.1534407852.localhost
Welcome to pprof!  For help, type 'help'.
(pprof) top 10
Total: 3006 samples
    2997  99.7%  99.7%     2997  99.7% main
       9   0.3% 100.0%        9   0.3% idle

使用可能遇到的问题

1.运行时出现:No nodes to print

程序逻辑使用CPU次数太少,无法分析

2.运行进出现:SIGPROF handler is already in use

使用了其它的性能分析工具如:gprof等,造成冲突

总结

简单探究了如何使用google-perftools工具配合http接口查看cpu分析结果

后续遇到问题还会继续更新

参考资料

C++ Profiler工具之初体验

gperftools 使用经验总结

16 Aug 2018