3

假设我有一个人为的程序:

#include <Windows.h>

void useless_function()
{
    Sleep(5000);
}

void useful_function()
{
    // ... do some work
    useless_function();
    // ... do some more work
}

int main()
{
    useful_function();
    return 0;
}

目标:我希望分析器告诉我useful_function()是不必要的调用useless_function()等待没有明显的原因。在 XPerf 下,这不会出现在我拥有的任何图表中,因为WaitForMultipleObjects()似乎是调用 toIdle.exe而不是我自己的程序。

这是我当前运行的 xperf 命令行:

xperf -on Latency -stackwalk Profile

有任何想法吗?

(这不仅限于等待函数。上述问题可能已通过在 处放置断点来解决NtWaitForMultipleObjects。理想情况下,可能有一种方法可以查看占用大量挂钟时间而不是仅 CPU 时间的堆栈样本)

4

3 回答 3

2

我认为您正在寻找的是Xperf 中带有就绪线程功能的等待分析。它捕获每个上下文切换,并在线程从睡眠(或其他阻塞的操作)唤醒后为您提供线程的调用堆栈。在您的情况下,您会在调用 sleep(5000) 之后看到堆栈以及睡眠时间。

该功能使用起来有点晦涩难懂。但幸运的是,这里有很好的描述:

使用 Xperf 的等待分析进行应用程序性能故障排除

于 2012-06-15T00:04:05.853 回答
1

等待分析是执行此操作的方法。你应该:

  • 记录 CSWITCH 提供者,以便获取所有上下文切换
  • 通过将 +CSWITCH 添加到 -stackwalk 参数来记录上下文切换时的调用堆栈
  • 可能会在就绪线程上记录调用堆栈,以通过将 +READYTHREAD 添加到您的 -stackwalk 来获取有关谁为您准备好的更多信息(即;谁发布了 Mutex 或 CS 或信号量以及在哪里)

然后,您使用 WPA(或 xperfview,但这是古老的)中的 CPU 使用率(精确)来查看上下文切换,并在不应闲置的线程上找到 TimeSinceLast 高的位置。您通常希望 CPU Usage (Precise) 中的列按以下顺序排列:

  • NewProcess(您的进程正在切换)
  • 新线程 ID
  • 新线程堆栈
  • ReadyingProcess(谁让你的线程准备好运行)
  • ReadyingThreadId(可选)
  • ReadyThreadStack(可选,在 -stackwalk 上需要 +ReadyThread)
  • 橙条
  • 数数
  • TimeSinceLast (us) - 按此列排序,通常
  • 无论您想要什么其他列

有关详细信息,请参阅我博客中的这些特定文章:- https://randomascii.wordpress.com/2014/08/19/etw-training-videos-available-now/ - https://randomascii.wordpress.com/2012/ 06/19/wpaxperf-trace-analysis-reimagined/

于 2015-02-22T05:45:25.713 回答
0

这个“分析器”会告诉你——只是随机暂停几次并查看堆栈。如果do some work耗时 5 秒,又do some more work耗时 5 秒,那么 33% 的时间堆栈将如下所示

main: calling useful_function
useful_function: calling useless_function
useless_function: calling Sleep

因此,大约 33% 的堆栈样本将准确显示这一点。任何花费部分挂钟时间的代码行都会出现在大约这部分样本上。

在其余的示例中,您会看到它在做其他事情。

有自动分析器以更漂亮的方式执行相同的操作,例如ZoomLTProf,尽管它们实际上并没有向您显示示例。

我查看了xperf文档,试图弄清楚您是否可以在挂钟时间获得堆栈样本并获得行级分辨率的百分比。看来你必须在 Windows 7 或 Vista 上。他们只关心功能,而不是线条,如果你有真正的大功能,这很重要。我不知道如何访问单个样本,我认为这对于了解程序为何花费时间很重要。

于 2010-11-13T20:36:50.600 回答