注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

勇敢的劳尤条

 
 
 

日志

 
 

linux下的程序分析工具——gprof  

2014-07-08 15:42:36|  分类: unix/linux |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

多线程开启gprof性能测试的简易方法

性能分析工具

软件的性能是软件质量的重要考察点,不论是在线服务程序还是离线程序,甚至是终端应用,性能都是用户体验的关键。这里说的性能重大的范畴来讲包括了性能和稳定性两个方面,我们在做软件测试的时候也是要重点测试版本的性能表现和稳定性的。对于软件测试过程中发现的性能问题,如何定位有很多的方法。基本的方法可能是开发者对代码进行review,或者是使用一些工具对代码进行性能分析。常见的性能分析tuning工具有哪些呢?下面两篇文章做了详细的总结:

在我工作中主要是关于Linux C++程序代码的性能分析,gprof是可用于Linux C++代码性能profiling的工具之一,本文主要讲讲我对gprof的学习和使用过程。


Gprof的基本原理

gprof能够让你知道你的代码哪些地方是比较耗时的,哪些函数是被调用次数很多的,并且能够让你一目了然的看到函数与函数之间的调用关系。gprof是gcc/g++编译器支持的一种性能诊断工具。只要在编译时加上-pg选项,编译器就会在编译程序时在每个函数的开头加一个mcount函数调用,在每一个函数调用之前都会先调用这个mcount函数,在mcount中会保存函数的调用关系图和函数的调用时间和被调次数等信息。最终在程序退出时保存在gmon.out文件中,需要注意的是程序必须是正常退出或者通过exit调用退出,因为只要在exit()被调用时才会触发程序写gmon.out文件。

那么,gprof的使用方法主要以下三步:

  • 会用-pg参数编译程序
  • 运行程序,并正常退出
  • 查看gmon.out文件

gprof <options> [executable-file] [profile-data-file(s)……] [>outfile]
可通过man gprof 查看各选项含义,通常会加上"-b"选项禁止显示冗长的说明信息。
executable-file如果没有指定,则会默认为a.out。
profile-data-file可跟多个文件,若没有指定,默认gmon.out。
统计信息较多,最好重定向到outfile方便查看。

Gprof使用实例

#include<iostream>  
using namespace std;  
  
#define MAX 10000000
void f() 
{
long long sum = 0;
for (long long i=0;i<MAX;i++)
sum += i;
}
void g() 
{
long long sum = 0;
for (long long i=0;i<MAX;i++)
sum += i;
f();
}
int main() 
{
long long sum = 0;
for (long long i=0;i<MAX;i++)
sum += i;
f();
g();
}

编译

g++ -o hello hello.cpp -pg -g

./hello
gprof -b ./hello gmon.out
得到

Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
42.06 0.05 0.05 2 25.23 25.23 f()
33.64 0.09 0.04 1 40.37 65.61 g()
25.23 0.12 0.03 main
0.00 0.12 0.00 1 0.00 0.00 _GLOBAL__sub_I__Z1fv
0.00 0.12 0.00 1 0.00 0.00 __static_initialization_and_destruction_0(int, int)


% time:各个函数占用的时间比率(不包括子函数),这一列加起来应该为100%
cumulative seconds:累积时间,当前行减去上一行即为当前函数耗费时间
self seconds:当前函数耗费时间(不包括子函数)
self calls:调用次数
ms/call:调用一次耗费的平均时间(不包括子函数),单位毫秒
total ms/call:同上,但包括子函数
name:函数名
可将gprof -b ./hello中的-b参数去掉,可以显示字段的详细含义描述
Call graph

granularity: each sample hit covers 2 byte(s) for 8.26% of 0.12 seconds

index % time self children called name
<spontaneous>
[1] 100.0 0.03 0.09 main [1]
0.04 0.03 1/1 g() [2]
0.03 0.00 1/2 f() [3]
-----------------------------------------------
0.04 0.03 1/1 main [1]
[2] 54.2 0.04 0.03 1 g() [2]
0.03 0.00 1/2 f() [3]
-----------------------------------------------
0.03 0.00 1/2 g() [2]
0.03 0.00 1/2 main [1]
[3] 41.7 0.05 0.00 2 f() [3]
-----------------------------------------------
0.00 0.00 1/1 __libc_csu_init [16]
[8] 0.0 0.00 0.00 1 _GLOBAL__sub_I__Z1fv [8]
0.00 0.00 1/1 __static_initialization_and_destruction_0(int, int) [9]
-----------------------------------------------
0.00 0.00 1/1 _GLOBAL__sub_I__Z1fv [8]
[9] 0.0 0.00 0.00 1 __static_initialization_and_destruction_0(int, int) [9]
-----------------------------------------------


Index by function name

[8] _GLOBAL__sub_I__Z1fv (hello.cpp) [2] g() [1] main
[3] f() [9] __static_initialization_and_destruction_0(int, int) (hello.cpp)

每个函数都分配了一个index,index按升序排列,一个函数对应一个entry,两个entry之间用虚线隔开。
在每个entry中,以[index]起头的行称为primary line。primary line上面的行称为caller's line,列举的是调用该函数的函数;下面的行subroutine's line列举的是该函数调用的子函数。这三种line的各项名称虽然相同,但有着截然不同的含义。
以下都以第二个entry为例说明:

primary line
index      % time    self     children    called        name
[2]              53.6    0.04       0.04          1             g() [2]
%time:g()耗费的时间比率。该比率包括了调用的f(),因此各个entry的该项数字加起来不等于100%。
self:同flat table的self seconds。
children:f()耗费的时间。下面的subroutines's line 的self项和children项之和应等于该数值。
called:只被调用了一次。

subroutine's line
index      % time      self       children       called        name
                                0.04       0.00            1/2           f() [3]
self:f()被g()调用过程中,f()的耗费时间0.04s。
children:f()被g()调用过程中,f()中的子函数耗费时间为0。
called:f()一共被调用了2次,其中有1次被g()调用。

caller's line
index      % time      self       children       called        name
                               0.04       0.04            1/1            main [1]
self:g()被main()调用过程中,g()的耗费时间。
children:g()被main()调用过程中,g()中的子函数耗费的时间。
called:g()一共被调用了1次,其中1次是被main()调用的。

【参考资料】

多线程开启gprof http://blog.csdn.net/jq0123/article/details/7818919

  评论这张
 
阅读(165)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017