5

正如标题所说,我想知道这两个命令之间的区别以及它们产生的结果。

通过阅读本文,我了解到 gprof 需要一个额外的标志(-g,gdb 也需要相同的标志?),但这并没有给我关于分析器之间差异的答案。

4

2 回答 2

6

gprof是专门发明的,因为prof只给你“自我时间”。“自我时间”告诉您在每个例程中找到程序计数器的总时间的比例。如果您需要考虑的唯一类型的“瓶颈”可以通过在调用堆栈底部减少周期来解决,那很好。

您通过减少对子例程的调用次数来解决的那种“瓶颈”呢?这就是gprof应该通过向呼叫者“收回”自我时间来帮助您找到的东西。例程中的“包含时间”包括它的“自身时间”,加上从它调用的例程中冒出来的时间。这是一个简单的例子gprof

在此处输入图像描述

A 调用 B 十次,B 调用 C 十次,C 为 10 个采样时间执行一些 CPU 密集型循环。请注意,没有一个样本落在 A 或 B 中,因为程序计数器几乎将所有时间都花在 C 中。 gprof通过计算调用并跟踪调用者,进行一些数学运算并向上传播时间。

所以你看,加速这个程序的一种方法是让 A 调用 B 的次数更少,或者让 B 调用 C 的次数更少,或者两者兼而有之。 prof不能给你那种信息——你必须猜测。

如果您正在考虑使用gprof,请注意它的问题,例如不提供行级信息,对 I/O 视而不见,对递归感到困惑,并误导您认为某些事情可以帮助您发现问题,例如采样率,调用图、调用计数等。请记住,它的作者只声称它是一个测量工具,而不是一个问题发现工具,尽管大多数人认为它是后者。

于 2013-07-12T12:33:44.257 回答
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显示调用图以显示函数内部也花费了时间。有了它,您可以找到在函数中花费时间的例程。

于 2013-07-12T12:40:18.920 回答