如何使用 Dtrace 计算任意 C 语句之间的时间
Posted
技术标签:
【中文标题】如何使用 Dtrace 计算任意 C 语句之间的时间【英文标题】:How can I use Dtrace to calculate the time taken between arbitrary C statements 【发布时间】:2018-12-25 12:21:39 【问题描述】:我正在使用 ImageMagick(通过 php imagick 扩展)生成一个简单的 gif 动画,就像这个。
我发现WriteGIFImage()
(https://github.com/ImageMagick/ImageMagick/blob/c807b69de68a33b42fc8725486d5ac81688afd16/coders/gif.c#L1506) 函数按照 D 脚本写入 gif 数据需要很长时间。
pid$target::WriteGIFImage:entry
self->start_WriteGIFImage = timestamp;
printf(" -> WriteGIFImage\n");
pid$target::WriteGIFImage:return
this->delta = (timestamp - self->start_WriteGIFImage) / 1000 / 1000;
@deltas["WriteGIFImage"] = sum(this->delta);
printf(" <- WriteGIFImage elapsed %d ms\n", this->delta);
// Output
ImagesToBlob
-> WriteImage
-> WriteGIFImage
<- WriteGIFImage elapsed 821 ms
<- WriteImage elapsed 821 ms
ImagesToBlob elapsed 821 ms
Total (ms):
RelinquishMagickMemory 0
WriteBlobByte 0
ImagesToBlob 821
WriteGIFImage 821
WriteImage 821
WriteGIFImage()
是一个很大的函数,我想知道 2 个语句之间花费的时间,以便找到最慢的代码块。例如我怀疑这个 for 循环需要很长时间,所以我需要 Dtrace 告诉我第 1673 行和第 1678 行之间的时间差异。如何使用 D 脚本来完成它?
1673 for (i=0; i < (ssize_t) image->colors; i++)
1674
1675 *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
1676 *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
1677 *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
1678
顺便说一句,我发现ScaleQuantumToChar()
和ClampToQuantum()
都是inline 函数,而pid*::ScaleQuantumToChar:entry/return
探针无法工作。如何用 D 跟踪内联函数?
【问题讨论】:
强烈建议使用调用clock()
来获取需要测量时间的两个点的当前CPU时间,那么经过的时间是ValueReturnedFromSecondCallToClock - ValueReturnedFromFirstCallToClock。您可以将结果除以 CLOCKS_PER_SECOND
以获得(更具可读性)经过的秒数
【参考方案1】:
除了entry
和return
探测器之外,pid
提供程序还具有针对每个指令偏移量的探测器。如果您执行sudo dtrace -l -n 'pid$target::WriteGIFImage:*' -p <pid>
,它将列出它们。然后,您必须反汇编代码以确定哪个偏移量对应于哪一行代码。而且,当一个程序是在打开优化的情况下构建的,这种对应关系可能不干净。 (相对于代码行,指令可能是乱序的。)
您还可以定义自己的用户定义的静态跟踪 (USDT) 提供程序,并使用它们检测您的代码。 dtrace
手册页解释了如何操作。
尽管如此,DTrace 可能不是最好的工具。使用 Instruments 的 Time Profiler 模板,它会告诉您程序将时间花在哪里,一直到行(甚至是指令)。
【讨论】:
以上是关于如何使用 Dtrace 计算任意 C 语句之间的时间的主要内容,如果未能解决你的问题,请参考以下文章