就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、参考资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,访问帮助中心 以获得指导。
Locked 。这个问题及其答案是locked 因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。
还有哪些程序可以与 gprof 做同样的事情?
gprof (阅读论文) 存在是有历史原因的。
如果您认为它会帮助您发现性能问题,那么它从未被宣传过。
论文是这样说的:
该概况可用于比较和评估成本
各种实施。
它并没有说它可以用来identify 需要评估的各种实施方式,尽管它确实imply 在特殊情况下它可以:
特别是如果发现程序的一小部分占据主导地位
执行时间处理时间。
那些不那么局部化的问题怎么办?
那些不重要吗?
不要寄予期望gprof 从未有人为此索赔过。
这是only 一种测量工具,并且仅适用于 CPU 密集型操作。
试试这个吧。
下面是 44 倍加速的示例。
这是 730 倍的加速。
这是一个 8 分钟的视频演示。
这是统计数据的解释。
这是对批评的回应。
有一个关于程序的简单观察。在给定的执行中,每条指令只占总时间的一部分(尤其是call
说明),从某种意义上说,如果没有它,就不会花时间。在此期间,指令位于堆栈上**。当你理解了这一点后,你就会发现——
gprof 体现了某些关于性能的神话,例如:
程序计数器采样很有用。 仅当您有不必要的热点瓶颈(例如大标量值数组的冒泡排序)时,它才有用。例如,一旦您将其更改为使用字符串比较的排序,它仍然是瓶颈,但程序计数器采样不会看到它,因为现在热点位于字符串比较中。另一方面,如果要采样extended 程序计数器(调用堆栈)、调用字符串比较的点、排序循环都清晰显示。实际上,gprof 是弥补仅 PC 采样的局限性的尝试。
计时功能比捕获耗时的代码行更重要。 这个神话的原因是gprof 无法捕获堆栈样本,因此它对函数进行计时,计算它们的调用次数,并尝试捕获调用图。然而,一旦识别出一个代价高昂的函数,您仍然需要在其内部查找负责该时间的行。如果有堆栈样本,您不需要查看,这些行将位于样本上。 (一个典型的函数可能有 100 - 1000 条指令。一个函数call 是 1 条指令,因此定位昂贵调用的精度要高 2-3 个数量级。)
调用图很重要。 关于程序你需要了解的不是where 它花费了时间,但是why 。当它在函数中花费时间时,堆栈上的每一行代码都给出了它为何存在的推理链中的一个链接。如果您只能看到堆栈的一部分,那么您只能看到部分原因,因此您无法确定该时间是否确实必要。
调用图告诉你什么?每条弧线都告诉您某个函数 A 在某个时间段内正在调用某个函数 B。即使 A 只有一行这样的代码调用 B,该行也只给出了一小部分原因。如果你足够幸运,也许这条线有一个糟糕的理由。通常,您需要同时查看多条线路才能找到不良原因(如果存在)。如果 A 在多个地方调用 B,那么它告诉你的信息就更少了。
递归是一个棘手且令人困惑的问题。 那只是因为gprof 其他分析器认为需要生成调用图,然后将时间归因于节点。如果有堆栈样本,则样本上出现的每一行代码的时间成本是一个非常简单的数字 - 它所在样本的分数。如果存在递归,则给定的行可以在样本上出现多次。不管。 假设每 N 毫秒采样一次,并且该线出现在其中 F% 上(单独或单独)。如果该行可以不花时间(例如删除它或围绕它分支),那么这些样本将消失 ,时间会减少F%。
时间测量的准确性(因此大量样本)很重要。 想一想。如果一行代码出现在 5 个样本中的 3 个上,那么如果您可以像灯泡一样将其射出,则所用时间大约会减少 60%。现在,您知道,如果您采集了 5 个不同的样本,您可能只会看到 2 次,或者最多 4 次。因此 60% 的测量值更像是 40% 到 80% 的一般范围。如果只有40%,你会说这个问题不值得解决吗?那么,当您真正想要的是时,时间准确性有什么意义呢?找到问题 ?
500 或 5000 个样本可以更精确地测量问题,但无法更准确地发现问题。
语句或函数调用的计数很有用。 假设您知道某个函数已被调用 1000 次。你能从中看出它花费了多少时间吗?您还需要知道平均运行需要多长时间,将其乘以计数,然后除以总时间。平均调用时间可能从纳秒到秒不等,因此仅计数并不能说明太多问题。如果存在堆栈样本,则例程或任何语句的成本只是其所在样本的分数。如果例程或语句可以不花时间,原则上可以节省这部分时间,因此这与性能有最直接的关系。
封锁时无需取样 造成这种误解的原因有两个:1)当程序等待时,PC 采样毫无意义;2)过分关注计时的准确性。然而,对于 (1),程序很可能正在等待它所请求的某些内容,例如文件 I/O,您可以需要知道 ,以及堆栈样本揭示的内容。 (显然,您希望在等待用户输入时排除样本。)对于(2),如果程序只是因为与其他进程竞争而等待,那么在运行时这可能会以相当随机的方式发生。
因此,虽然程序可能需要更长的时间,但这不会对重要的统计数据(语句在堆栈上的时间百分比)产生很大影响。
“自我时间”很重要 仅当您在函数级别而不是线路级别进行测量时,自时间才有意义,并且您认为需要帮助来辨别函数时间是否进入纯粹的本地计算与调用的例程。如果在行级别进行汇总,则一行如果位于堆栈末尾则表示自身时间,否则表示包含时间。无论哪种方式,它的成本都是它所在的堆栈样本的百分比,因此无论哪种情况都可以为您找到它。
必须以高频率取样 这是因为性能问题可能会快速发生,并且样本必须频繁才能解决。但是,如果问题的成本是 10 秒(或其他)总运行时间中的 20%,那么无论问题是否发生,总时间内的每个样本都有 20% 的机会命中它像这样的单件
.....XXXXXXXX...........................
.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^
(20 个样本,4 个命中) 或者像这样分成许多小块
X...X...X.X..X.........X.....X....X.....
.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^.^
(20 个样本,3 个命中) 无论哪种方式,无论采样多少样本,命中次数平均约为五分之一。 (平均值 = 20 * 0.2 = 4。标准差 = +/- sqrt(20 * 0.2 * 0.8) = 1.8。)
你正在寻找的the 瓶颈 就好像只有一个一样。考虑以下执行时间表:vxvWvzvWvxvWvYvWvxvWv.vWvxvWvYvW
它由真正有用的工作组成,代表为.
。存在性能问题vWxYz
分别花费 1/2、1/4、1/8、1/16、1/32 的时间。抽样发现v
容易地。它被删除,留下
xWzWxWYWxW.WxWYW
现在程序的运行时间减少了一半,现在W
花费一半的时间,并且很容易找到。它被删除,留下
xzxYx.xY
此过程持续进行,每次都会消除按百分比计算的最大性能问题,直到找不到任何可消除的问题。现在唯一执行的是.
,其执行时间是原始程序的 1/32。这是放大效应 ,通过消除任何问题会使余数更大(按百分比计算),因为分母减少了。 另一个关键点是必须找到每一个问题 - 5个都没有遗漏。任何未发现和修复的问题都会严重降低最终的加速比。仅仅找到一些,但不是全部,还不够“足够好”。
补充:我只想指出一个原因gprof 很受欢迎 - 正在被教导,
大概是因为它是免费的,易于教学,而且已经存在很长时间了。
快速谷歌搜索可以找到一些教授(或似乎教授)的学术机构:
伯克利分校克莱姆森分校
科罗拉多州 厄勒姆公爵 佛罗里达州立大学 印第安纳州 密西根州立大学
NCSA. 伊利诺伊州 NCSU 纽约大学 或 普林斯顿大学 PSU
斯坦福大学 UCSD UMD UMICH 犹他州 UTEXAS UTK Wustl
** 除了请求完成工作的其他方式外,不会留下任何痕迹why ,例如通过消息发布。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)