2

我一直在使用 oprofile 试图找出为什么我的程序在内核中花费了这么多时间。我现在有来自内核的符号,但显然我的程序和内核之间没有链接可以告诉我我的程序的哪些部分花费了这么长时间。

samples  %        image name               app name                 symbol name
-------------------------------------------------------------------------------
  201       0.8911  vmlinux-3.0.0-30-generic vmlinux-3.0.0-30-generic _raw_spin_lock_irq
  746       3.3073  vmlinux-3.0.0-30-generic vmlinux-3.0.0-30-generic rb_get_reader_page
  5000     22.1671  vmlinux-3.0.0-30-generic vmlinux-3.0.0-30-generic default_spin_lock_flags
  16575    73.4838  vmlinux-3.0.0-30-generic vmlinux-3.0.0-30-generic _raw_spin_lock
22469    11.1862  vmlinux-3.0.0-30-generic vmlinux-3.0.0-30-generic __ticket_spin_lock
  22469    99.6010  vmlinux-3.0.0-30-generic vmlinux-3.0.0-30-generic __ticket_spin_lock [self]
  26        0.1153  vmlinux-3.0.0-30-generic vmlinux-3.0.0-30-generic ret_from_intr

我从这里去哪里?如何发现程序中导致 __ticket_spin_lock 的位置?

4

2 回答 2

4

Oprofile 获取堆栈样本。您需要做的不是查看它们的摘要,而是实际检查原始样本。例如,如果您将 30% 的时间花在内核中,那么如果您可以看到随机选择的 10 个堆栈样本,您可以期望其中 3 个或多或少地向您展示您如何进入内核的全部原因核心。

这样,您将看到摘要或调用图不会向您显示的内容。

以防万一:由于__ticket_spin_lock99.6% 的时间都在堆栈上,因此在您查看的每个堆栈样本上,您将看到 99.6% 的概率是您如何进入该例程的。然后,如果您真的不需要这样做,您可能会获得 250 倍的加速。这就像从四分钟到一秒。使用“正确”或“自动化”的方法——得到结果。

补充:关于分析器的事情是它们很受欢迎,有些用户界面非常漂亮,但遗憾的是,这恐怕是“皇帝的新装”的案例。如果这样的工具找不到太多需要修复的地方,你会喜欢它,因为它说(可能是错误的)你写的代码接近最优。

有很多帖子推荐这个或那个分析器,但我不能指出任何声称使用分析器可以节省超过百分之几的时间,比如 40%。也许有一些。

从未听说过首先使用探查器来获得加速,然后再次使用来获得第二次加速,依此类推。这就是你获得真正加速的方式——多重优化。一开始只是一个小性能问题的东西在你删除了一个更大的问题之后不再是小问题。这张图显示了通过消除六个问题,加速是如何接近三个数量级的。您不一定可以这样做,但不值得尝试吗?

在此处输入图像描述

为进一步编辑道歉。我只是想表明很容易欺骗调用图。红线代表调用堆栈样本。在这里,A1 将所有时间都花在调用 C2 上,反之亦然。然后假设您保持相同的行为,但是您放入了“调度”例程 B。现在调用图丢失了 A1 在 C2 中花费的所有时间的信息,反之亦然。您可以轻松地将此示例扩展到多个级别。 在此处输入图像描述 你可以说调用会看到这一点。好吧,这就是你如何欺骗调用树的方法。A 将所有时间都花在调用 C 上。现在,如果 A 调用 B1、B2、... C 是隐藏的。 在此处输入图像描述 还有许多其他完全普通的编程实践会混淆这些工具,特别是当样本深度为 10-30 层且功能都很少时,但程序员仔细检查适量样本时无法隐藏这些关系。

于 2013-04-03T00:21:40.280 回答
2

我同意迈克的回答:调用图不是检查问题根源的正确方法。您真正想要的是查看最热门样本的调用链。

如果您不想“手动”检查 oprofile 收集的原始样本,您可以使用 -g 选项使用perfrecord命令重新运行您的应用程序,以收集堆栈跟踪。然后,您可以使用perf 命令显示带有调用链注释的示例。由于 perf 没有在全局调用图中聚合单个样本的调用链,因此您没有 Mike 的帖子中概述的一些问题。report

于 2013-04-07T23:24:05.147 回答