prof和gprof有什么区别?

时间:2013-07-12 10:02:49

标签: c profiling

就像标题所说的那样,我想知道两个命令之间的差异以及它们产生的结果。

从阅读this我明白gprof需要一个额外的标志(-g,gdb需要同样的吗?),但这并没有给我一个关于分析器之间差异的答案。

2 个答案:

答案 0 :(得分:5)

gprof是专门发明的,因为prof只会给你“自我时间”。 “自我时间”告诉您在每个例程中找到程序计数器的总时间的小部分。 如果您需要考虑的唯一类型的“瓶颈”可以通过调用堆栈底部的剃须循环来解决,那就没问题了。

通过减少对子程序的调用次数,你解决了什么“瓶颈”? 这就是gprof应该帮助你找到的东西,通过“向自己的时间”回拨给呼叫者。 例程中的“包容时间”包括其“自我时间”,以及它所调用的例程中的泡沫。 以下是gprof所做的一个简单示例:

enter image description here

A调用B十次,B调用C十次,C执行一些CPU密集型循环10次。 请注意,没有一个样本落在A或B中,因为程序计数器实际上在C中花费了所有时间。 gprof,通过计算呼叫数量,并跟踪谁制作它们,进行一些数学计算并向上传播时间。

所以你看,加速这个程序的方法是让A呼叫B次数减少,或者让B呼叫C的次数减少,或两者兼而有之。 prof无法向您提供此类信息 - 您必须猜测。

如果您正在考虑使用gprofbe 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 显示调用图以显示函数内部的时间。有了这个,你就可以找到在函数中花费时间的例程。