【发布时间】:2011-06-26 06:02:05
【问题描述】:
这是一个臃肿的问题,所以我提前道歉。我很好奇gprof 在低技术水平上是如何工作的。我知道它是由计时器完成的,但是为什么需要专门编译可执行文件才能进行分析?编译是否会导致为统计分配空间?
另外,时间是如何准确地完成的?
【问题讨论】:
这是一个臃肿的问题,所以我提前道歉。我很好奇gprof 在低技术水平上是如何工作的。我知道它是由计时器完成的,但是为什么需要专门编译可执行文件才能进行分析?编译是否会导致为统计分配空间?
另外,时间是如何准确地完成的?
【问题讨论】:
好吧,这给出了good explanation。这也解释了statistical profiling
本质上,gprof 将更改程序的可执行文件(这称为插入代码)以存储一些簿记信息,例如一个函数被调用了多少次。
统计分析位来自定期窥探程序计数器以获取代码正在执行的示例。
Gprof 两者都做。它检测代码并通过查看程序计数器来收集样本。
【讨论】:
刚刚read the paper(再次),让我试着解释一下。
假设它以 100Hz 的频率进行采样,除非进程因 IO 或其他原因而被阻塞。每个样本都记录了PC,它在某些功能中。该函数中的样本计数会增加。
因此,在运行结束时,如果有(例如)1000 个样本,则意味着总执行时间(仅 CPU)为 10 秒。如果例程 B 记录了 500 个这些样本,这意味着它的总执行时间是总数的 1/2,即 5 秒。这是它的自我时间,因为 PC 就在其中。这并不能说明执行平均需要多长时间。要说明这一点,您需要知道它被调用了多少次。它也不包括在被调用者中花费的时间。
当使用 -pg 标志编译代码时,会在每个例程的入口代码中插入一个特殊调用。这注意到例程 B 已进入,并且它注意到它是从例程 A 中的调用站点调用的。有一个由该调用站点索引的表,可以在其中计算该调用。所以最后,gprof 可以知道总共调用了多少次 B,其中有多少次来自 A。
为了得到B的平均self time,它的总self time除以它被调用的次数。
为了得到例程A的总累积时间(自身加上被调用者),gprof需要A的自身时间,加上它调用每个下级例程B的总次数,乘以B的平均累积时间。然后将 number 除以对 A 的调用总数,得到 A 的平均累积时间。
听起来不错,直到递归进入图片,它变得更加混乱。
这一切都非常聪明,正如作者指出的那样,充满了警告。
【讨论】:
-finstrument-functions 选项有什么区别?
-finstrument-functions 是 a gcc option(不是 gprof),它允许您将编写的进入和退出函数放入编译器处理的每个例程中。它只给你调用者和被调用者的地址,所以你必须做一些后处理。如果你想做计时,你必须弄清楚如何做。距离诊断性能问题还有很长的路要走。我在this short video 中展示了一个简单的方法。