【发布时间】:2011-03-16 20:50:30
【问题描述】:
我来自 Matlab 背景,所以我习惯使用分析器来分析每一行,而不仅仅是像 gprof 或 callgrind 这样的每个函数。 C 是否有具有类似功能的分析器?
谢谢!
【问题讨论】:
-
关于 SO 上的分析工具等的许多建议,参见例如stackoverflow.com/questions/1168766/…
我来自 Matlab 背景,所以我习惯使用分析器来分析每一行,而不仅仅是像 gprof 或 callgrind 这样的每个函数。 C 是否有具有类似功能的分析器?
谢谢!
【问题讨论】:
我相信callgrind 会这样做。我知道它会计算每行的周期数,但我不确定“时间”。
【讨论】:
Shark 是 Mac OS X 中的分析工具之一,可以做到这一点(甚至可以通过指令进行分析)。我知道您的屏幕截图是在 Windows 上,所以这可能没有帮助,但也许您可以在 Mac 上运行您的代码。你可以试试Very Sleepy,但我没用过,不知道它有多好。
【讨论】:
您可以使用 GNU 实用程序 GCOV 进行逐行分析。从 GCC Docs 运行示例。
$ gcc -fprofile-arcs -ftest-coverage tmp.c
$ a.out
$ gcov tmp.c
90.00% of 10 source lines executed in file tmp.c
Creating tmp.c.gcov
文件 tmp.c.gcov 包含如下输出:
-: 0:Source:tmp.c
-: 0:Graph:tmp.gcno
-: 0:Data:tmp.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:
-: 3:int main (void)
1: 4:{
1: 5: int i, total;
-: 6:
1: 7: total = 0;
-: 8:
11: 9: for (i = 0; i < 10; i++)
10: 10: total += i;
-: 11:
1: 12: if (total != 45)
#####: 13: printf ("Failure\n");
-: 14: else
1: 15: printf ("Success\n");
1: 16: return 0;
-: 17:}
【讨论】:
Check this link 和 try this method。
像 Mandelbrot 这样的例子的问题在于它不是一个非常大的程序。在现实世界的软件中,调用树变得更深,更密集,所以你需要找出每行或每条指令,它负责的时间百分比,这只是它在调用中的时间百分比堆。因此,您需要对调用堆栈进行采样并告诉您,对于出现在那里的每一行或每条指令,它所在的样本百分比是多少。您不需要高精度的测量 - 这是神话之一。
有一些工具可以做到这一点,一个是RotateRight/Zoom,另一个是LTProf。我个人发誓完全手动的方法。
在过去的几天里,我们在这里的一些代码中遇到了性能问题。通过手动方法,我找到了一种节省 40% 的方法。然后我找到了一种在此基础上节省 40% 的方法,总共节省了 64%。这只是一个例子。 Here's an example of saving over 97%.
补充:这可能会限制潜在的加速。假设存在三个问题。问题 A(在您的代码中)需要 1/2 的时间。问题 B(在 Jerry 的代码中)需要 1/4 的时间,问题 C(在您的代码中)需要 1/8 的时间。当你采样时,问题 A 跳出来,因为它是你的代码,你修复它,现在程序花费了原始时间的 1/2。然后你再次采样,问题 B(现在是 1/2)就跳出来了。你看到它在 Jerry 的代码中,所以你必须向 Jerry 解释它,尽量不让他难堪,并问他是否可以解决它。如果他出于某种原因不这样做(就像那是他最喜欢的一些代码),那么即使你修复了问题 C,时间也只能减少到原始时间的 3/8。如果他确实修复了它,您可以修复 C 并降低到原始时间的 1/8。然后可能还有另一个问题 D(你的),如果你修复它可以将时间缩短到原始时间的 1/16,但如果 Jerry 不解决问题 B,你不能做得比 5/16 更好。这就是社交互动在性能调整中绝对至关重要的原因。
我见过的唯一有效的技巧(因为它被用在我身上)是以悲伤、抱歉的语气呈现信息,就好像这是你的问题,并且坚持呈现信息。歉意的语气化解了尴尬,执着让他不断思考。
【讨论】:
我们的SD C Profiler 工具适用于 GCC 源代码。它提供基本块而不是线的分析;这会以相当低的开销提供相同的确切信息。
【讨论】: