4

gprof在一个 C++ 程序上运行16.637s,根据time(),我在输出的第一行得到了这个:

%   cumulative   self              self     total           
time   seconds   seconds    calls   s/call   s/call  name    
31.07      0.32     0.32  5498021     0.00     0.00  [whatever]

31.07%如果只需要几秒钟,为什么它会列出时间.32?这是每次通话时间吗?(那不是自己打电话吗?)

这是我第一次使用gprof,所以请善待:)

编辑:通过向下滚动,gprof 似乎只认为我的程序需要 1.03 秒。为什么它会变得如此错误?

4

6 回答 6

9

结果发现瓶颈出现在文件 I/O 中(请参阅Is std::ifstream 明显慢于 FILE?)。我切换到读取缓冲区中的整个文件,它的速度大大加快。

这里的问题是 gprof 在等待文件 I/O 时似乎没有生成准确的分析(参见http://www.regatta.cs.msu.su/doc/usr/share/man/info/ru_RU/a_doc_lib /cmds/aixcmds2/gprof.htm)。事实上,seekg甚至tellg不在分析列表上,他们是瓶颈!

于 2009-02-01T21:04:43.880 回答
6

Self seconds是在 [whatever] 中花费的时间。

累积秒数是在 [whatever] 和它上面的调用中花费的时间(例如 [whatever] + main)

这些都不包括在从 [whatever] 调用的函数中花费的时间。 这就是为什么您没有看到更多时间列出的原因。

例如,如果您的 [whatever] 函数正在调用大量 printf,那么您的 gprof 输出会告诉您 printf 大部分时间都在吃东西。

于 2009-01-27T23:53:52.987 回答
2

这似乎是对如何阅读 gprof 输出的一个很好的概述。您正在查看的 31.07% 是 gprof 认为仅用于该函数(不包括它调用的函数)的总运行时间的一部分。赔率是百分比如此之大而时间很小的原因是 gprof 认为该程序不会像你那样花很长时间。这很容易通过向下滚动 gprof 输出的第一部分来检查:累积秒数会越来越大,直到它限制在程序的总运行时间(从 gprof 的角度来看)。我想你会发现这大约是 1 秒,而不是你期望的 16 秒。

至于为什么会有这么大的差异,我也说不上来。也许 gprof 没有看到所有的代码。或者您在分析时是否在检测代码上使用了时间?我不希望它能正常工作......

于 2009-01-28T22:58:55.813 回答
1

您是否尝试过此问题中提到的其他一些工具?他们如何比较会很有趣。

于 2009-01-28T00:23:01.540 回答
1

您遇到了gprof和其他基于相同概念的分析器常见的问题 - 1) 对程序计数器进行采样以获得某种直方图,2) 测量函数以测量时间、计数并获取调用图。

对于实际定位性能问题,他们没有抓住重点。
这不是关于测量例程,而是关于找到有罪的代码。

假设您有一个采样器,它以随机的挂钟时间对程序进行频闪 X 射线扫描。在每个示例中,程序可能位于 I/O 中间,可能位于您编译的代码中,也可能位于某些库例程中,例如malloc

但不管它在哪里,它花费那段时间的责任是由调用堆栈上的每一行代码共同分担的,因为如果没有进行任何一个调用,它就不会在携带过程中完成该电话要求的工作。

因此,请查看显示在调用堆栈的多个样本上的每一行代码(样本越多越好)。那就是钱的所在。不要只看程序计数器在哪里。在堆栈的上方有“深口袋”。

于 2009-11-23T21:22:04.497 回答
0

是的,这些“秒”值不是每次调用。百分比时间适用于程序的整个运行。实际上,您的程序在该函数中花费了 31% 的时间(由于调用次数 + 每次调用所花费的时间)。

您可能想了解如何分析 gprof 的平面配置文件。

更正:对不起,前两秒的值是 OP 指出的累积值。

我认为奇怪的是,您看到“self”和“total s/call”为 0。

引用关于gprof 准确性的部分:“实际的误差量通常不止一个采样周期。事实上,如果一个值是采样周期的 n 倍,那么它的预期误差是 n 个采样周期的平方根。如果采样周期为 0.01 秒,foo 的运行时间为 1 秒,foo 运行时间的预期误差为 0.1 秒。从一次分析运行到下一次,平均可能会有这么大的差异。(有时会有所不同更多的。)”

此外,可能相关的是,可能值得注意的是 gprof 不会分析多线程程序。在这种情况下,您最好使用SysprofOProfile之类的东西。

于 2009-01-27T22:48:46.940 回答