就像标题所说的那样,我想知道两个命令之间的差异以及它们产生的结果。
从阅读this我明白gprof需要一个额外的标志(-g,gdb需要同样的吗?),但这并没有给我一个关于分析器之间差异的答案。
答案 0 :(得分:5)
gprof
是专门发明的,因为prof
只会给你“自我时间”。
“自我时间”告诉您在每个例程中找到程序计数器的总时间的小部分。
如果您需要考虑的唯一类型的“瓶颈”可以通过调用堆栈底部的剃须循环来解决,那就没问题了。
通过减少对子程序的调用次数,你解决了什么“瓶颈”?
这就是gprof
应该帮助你找到的东西,通过“向自己的时间”回拨给呼叫者。
例程中的“包容时间”包括其“自我时间”,以及它所调用的例程中的泡沫。
以下是gprof
所做的一个简单示例:
A调用B十次,B调用C十次,C执行一些CPU密集型循环10次。
请注意,没有一个样本落在A或B中,因为程序计数器实际上在C中花费了所有时间。
gprof
,通过计算呼叫数量,并跟踪谁制作它们,进行一些数学计算并向上传播时间。
所以你看,加速这个程序的方法是让A呼叫B次数减少,或者让B呼叫C的次数减少,或两者兼而有之。
prof
无法向您提供此类信息 - 您必须猜测。
如果您正在考虑使用gprof
,be aware of its problems,就像不提供行级别信息,对I / O视而不见,对递归感到困惑,并误导您认为某些事情有帮助你会发现问题,如采样率,调用图,调用计数等。
请记住,其作者仅声称它是一种测量工具,而不是一种问题查找工具,即使大多数人认为它是后者。
答案 1 :(得分:2)
据我所知,两个命令都输出了类似的平面文件,如下所示:
扁平资料
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls us/call us/call name
37.50 0.15 0.15 48000 3.12 3.12 Life::neighbor_count(int, int)
17.50 0.22 0.07 _IO_do_write
10.00 0.26 0.04 __overflow
7.50 0.29 0.03 _IO_file_overflow
7.50 0.32 0.03 _IO_putc
5.00 0.34 0.02 12 1666.67 14166.67 Life::update(void)
5.00 0.36 0.02 stdiobuf::overflow(int)
5.00 0.38 0.02 stdiobuf::sys_write(char const *, int)
2.50 0.39 0.01 ostream::operator<<(char)
2.50 0.40 0.01 internal_mcount
0.00 0.40 0.00 12 0.00 0.00 Life::print(void)
0.00 0.40 0.00 12 0.00 0.00 to_continue(void)
0.00 0.40 0.00 1 0.00 0.00 Life::initialize(void)
0.00 0.40 0.00 1 0.00 0.00 instructions(void)
0.00 0.40 0.00 1 0.00 170000.00 main
平面配置文件显示程序执行每个功能所花费的总时间。
gprof 似乎再输出一个代表调用图的文件,它看起来像:
致电图:
granularity: each sample hit covers 4 byte(s) for 2.50% of 0.40 seconds
index % time self children called name
0.02 0.15 12/12 main [2]
[1] 42.5 0.02 0.15 12 Life::update(void) [1]
0.15 0.00 48000/48000 Life::neighbor_count(int, int) [4]
-----------------------------------------------
0.00 0.17 1/1 _start [3]
[2] 42.5 0.00 0.17 1 main [2]
0.02 0.15 12/12 Life::update(void) [1]
0.00 0.00 12/12 Life::print(void) [13]
0.00 0.00 12/12 to_continue(void) [14]
0.00 0.00 1/1 instructions(void) [16]
0.00 0.00 1/1 Life::initialize(void) [15]
-----------------------------------------------
[3] 42.5 0.00 0.17 _start [3]
0.00 0.17 1/1 main [2]
-----------------------------------------------
0.15 0.00 48000/48000 Life::update(void) [1]
[4] 37.5 0.15 0.00 48000 Life::neighbor_count(int, int) [4]
-----------------------------------------------
调用图显示每个函数及其子函数花费的时间。根据这些信息,您可以找到虽然它们本身可能没有花费太多时间的功能,但却调用了其他使用了异常时间的功能。
最后: 似乎 prof 只显示在函数中花费的时间,而 gprof 显示调用图以显示函数内部的时间。有了这个,你就可以找到在函数中花费时间的例程。