如何使用Dtrace计算任意C语句之间的时间

时间:2018-12-25 12:21:40

标签: c dtrace

我正在使用ImageMagick(通过PHP imagick扩展)生成一个简单的gif动画,就像这样。

enter image description here

我发现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跟踪内联函数?

1 个答案:

答案 0 :(得分:2)

除了entryreturn探针外,pid提供者还为每个指令偏移量提供探针。如果您执行sudo dtrace -l -n 'pid$target::WriteGIFImage:*' -p <pid>,它将列出它们。然后,您必须分解代码以确定哪些偏移量对应于代码的哪一行。而且,在构建启用了优化的程序时,这种对应关系可能并不干净。 (相对于代码行,指令可能会乱序。)

您还可以定义自己的用户定义的静态跟踪(USDT)提供程序,并使用它们来检测代码。 dtrace手册页介绍了操作方法。

尽管如此,但DTrace可能不是最好的工具。使用Instruments的Time Profiler模板,它将告诉您程序在哪里花费时间,一直到代码行(甚至是指令)。