Ope*_*way 2 c++ profiling gprof kcachegrind
使用两者来分析一些C++数字运算代码,gprof并kcachegrind为对执行时间贡献最大的函数(取决于输入的50-80%)给出类似的结果,但对于10-30%之间的函数,这些工具都给出不同的结果.这是否意味着其中一个不可靠?你会怎么做?
gprof实际上非常原始.这是它的作用.1)以恒定速率对程序计数器进行采样,并记录每个功能中有多少样本(独占时间).2)计算任何功能的多少次调用的任何函数B.从它可以找出每个函数被调用多少次在总,什么是平均独占时间.为了获得每个函数的平均包含时间,它在调用图中向上传播独占时间.
如果您希望这具有某种准确性,您应该了解一些问题.首先,它只计算CPU进程中的时间,这意味着它对I/O或其他系统调用是盲目的.其次,递归混淆了它.第三,功能总是遵循平均运行时间的前提,无论何时被呼叫或者呼叫它们,都是非常可疑的.第四,函数(和它们的调用图)是你需要知道的而不是代码行的概念,仅仅是一种流行的假设,仅此而已.第五,测量精度甚至与发现"瓶颈" 相关的概念也只是一种流行的假设,仅此而已.
Callgrind可以在线路级别工作 - 这很好.不幸的是,它与其他问题有关.
如果您的目标是找到"瓶颈"(而不是进行常规测量),您应该看一下逐行报告的挂钟时间堆栈采样器,例如缩放.原因很简单,但可能不熟悉.
假设你有一个程序,其中一组函数相互调用,总共需要10秒钟.此外,还有一个采样器是样品,不只是程序计数器,而是整个调用堆栈,它确实这一切的时候以恒定的速率,如每秒100次.(暂时忽略其他进程.)
所以最后你有1000个调用堆栈样本.选择出现在多个代码中的任何代码行L. 假设您可以通过避免它,删除它或将其传递给真正非常快的处理器来以某种方式优化该线.
那些样品会发生什么?
由于该行代码L现在(基本上)没有时间,所以没有样本可以点击它,因此这些样本将消失,减少样本总数,从而减少总时间!实际上,总时间将减少L在堆栈上的时间分数,这大致是包含它的样本的分数.
我不想太统计,但很多人认为你需要大量的样本,因为他们认为测量的准确性很重要.它不是,如果你这样做的原因是要找出解决方法以获得加速.重点是找到要修复的内容,而不是测量它.L行在堆栈的某个F部分的时间,对吧?所以每个样本都有一个击中它的概率F,对吧?就像掷硬币一样.有一种理论,称为继承规则.它说(在简化但一般的假设下),如果你掷硬币N次,并看到"头"S次,你可以估计硬币F的公平性(平均)(S+1)/(N+2).所以,如果你只拿三个样本,并在其中两个看到L ,你知道F是什么吗?当然不是.
但你确实知道它是(2 + 1)/(3 + 2)或60%.因此,你可以通过"优化"L线来节省(平均)多少时间.当然,堆栈样本显示了 L行("瓶颈"**)的确切位置.你没有把它测量到两位或三位小数真的很重要吗?
顺便说一句,它不受上述所有其他问题的影响.
**我一直在引用"瓶颈",因为使大多数软件变慢的原因与瓶颈没有任何共同之处.一个更好的比喻就是"消耗" - 只是不必要地浪费时间.