Google的gperftools套件中包含有CPU Profiler(以下简称:pprof),原生支持C/C++多线程程序的性能剖析。相比GNU Profiler无法原生支持多线程性能剖析,pprof更具实用价值。
gperftools:https://googledrive.com/host/0B6NtGsLhIcf7MWxMMF9JdTN3UVk/gperftools-2.2.tar.gz
cmake:http://www.cmake.org/download/
The KDE Software Development Kit(kdesdk):内含kcachegrind工具,系统盘中包含该rpm包。
完整项目见:https://github.com/lostaway/Woody-Ye-s-Code-Share/tree/master/CpuProfilerExample
// main.cpp
#include
#include
void *FastFunc(void *_arg)
{
double sum = 0;
for(int i = 0; i < 100000000; i++)
{
sum += 1;
}
return (NULL);
}
void *SlowFunc(void *_arg)
{
double sum = 0;
for(int i = 0; i < 100000000; i++)
{
sum *= 3;
sum /= 3;
sum += 1;
}
return (NULL);
}
void *AllFunc(void *_arg)
{
FastFunc(NULL);
SlowFunc(NULL);
return (NULL);
}
int main(int argc, char *argv[])
{
pthread_t tidFast = 0, tidSlow = 0, tidAll = 0;
pthread_create(&tidFast, NULL, FastFunc, NULL);
pthread_create(&tidSlow, NULL, SlowFunc, NULL);
pthread_create(&tidAll, NULL, AllFunc, NULL);
pthread_join(tidFast, NULL);
pthread_join(tidSlow, NULL);
pthread_join(tidAll, NULL);
return (0);
}
# CMake compile script
PROJECT(CpuProfilerExample)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# usage "cmake -DUSE_CPU_PROFILER=ON .." or "cmake -DUSE_CPU_PROFILER=OFF .."
MESSAGE(STATUS USE_CPU_PROFILER=${USE_CPU_PROFILER})
SET(SRC main.cpp)
INCLUDE_DIRECTORIES()
LINK_DIRECTORIES($ENV{GPERFTOOLS_ROOT}/lib)
ADD_EXECUTABLE(CpuProfilerExample ${SRC})
TARGET_LINK_LIBRARIES(CpuProfilerExample pthread)
IF(USE_CPU_PROFILER)
TARGET_LINK_LIBRARIES(CpuProfilerExample profiler)
ENDIF()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#!/bin/sh
echo "start CpuProfilerExample CPU profile"
env CPUPROFILE=CpuProfilerExample.prof ./CpuProfilerExample
exit 1
#!/bin/sh
echo "Display CpuProfilerExample CPU profile in Kcachegrind"
pprof --callgrind CpuProfilerExample CpuProfilerExample.prof > CpuProfilerExample.callgrind
nohup kcachegrind CpuProfilerExample.callgrind > /dev/null &
exit 1
pprof可以在不修改源码的情况下,通过在编译时链接profiler库,程序启动前设置特定的环境变量来开启CPU剖析功能。进入CpuProfilerExample项目根目录:
$ mkdir build
$ cmake -DUSE_CPU_PROFILER=ON ..
$ gmake
$ cd ../bin
$ ./startCpuProfile.sh
程序运行结束后,在bin目录下会生成“CpuProfilerExample.prof”性能剖析文件。执行:
$ ./displayProfileInKcachegrind.sh
启动KCacheGrind程序,显示出性能剖析结果:
调用图中,每个矩形框表示一个函数,上部是函数名,下部表示该函数及其调用的函数占程序总运行时间的百分比。仅从百分比来看,执行了浮点数乘除加操作的SlowFunc函数,占了总运行时间的85.39%,与实际代码相符。执行了浮点数加的FastFunc函数,占总运行时间的14.61%。
剖析结果中还有“时间片”的概念。见左侧函数列表,start_thread的Called字段“527”,表示start_thread函数调用的函数共消耗了527个时间片。具体每个调用的函数消耗的时间片数量,标示在调用图的箭头上。所以,从占用百分比和占用时间片来看,SlowFunc函数是示例程序的性能瓶颈。
程序性能优化,本是慢工细活,有了pprof可以很快速的定位到程序的性能瓶颈,针对性的做优化。在熟悉了pprof的基本用法之后,进一步学习的目标应该是分析工作中复杂程序的性能瓶颈、第三方库的性能瓶颈和系统调用的性能瓶颈。
[1] Google CPU Profiler Manuals,http://gperftools.googlecode.com/svn/trunk/doc/cpuprofile.html