我一直在使用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的地方?
答案 0 :(得分:4)
Oprofile采用堆栈样本。您需要做的不是查看它们的摘要,而是实际检查原始样本。如果您在内核中花费30%的时间,那么如果您可以看到随机选择的10个堆栈样本,您可以预期其中3个或多或少地向您展示您如何进入内核。
That way you will see things摘要或调用图表不会显示给您。
如果不清楚:由于__ticket_spin_lock
在99.6%的时间内在堆栈上,然后在您查看的每个堆栈样本,概率为99.6%你会看到你如何进入那个例行公事。
然后如果你真的不需要这样做,你可能有250倍的加速。
这就像从四分钟到一秒钟。拧紧“正确”或“自动”方法 - 获得结果。
ADDED:有关分析器的事情是它们很受欢迎,有些具有非常好的UI, 但遗憾的是,我担心,这是“皇帝的新衣服”。 如果这样的工具找不到太多需要解决的问题,那么你会喜欢它,因为它(可能是错误地)说你的代码(如所写的)接近最优。
有很多帖子推荐这个或那个探查器,但是 我不能指出使用分析器节省超过百分之几的时间,例如40%。 也许有一些。
我从未听说过首先使用的探查器获得加速,然后再次使用以获得第二次加速,依此类推。 这就是你如何获得真正的加速 - 多重优化。 在删除较大的一个之后,开始时只是一个小的性能问题就不再那么小了。 这张照片显示,通过消除六个问题,加速几乎是三个数量级。 你不一定能这样做,但不值得尝试吗?
APOLOGIES进一步编辑。我只是想表明它是愚弄一个调用图。 红线代表调用堆栈样本。 A1在这里花费所有时间来调用C2,反之亦然。然后假设你保持相同的行为,但你输入了“调度”例程B. 现在,调用图丢失了A1在C2中花费的所有信息,反之亦然。 您可以轻松地将此示例扩展到多个级别。 你可以说一个电话树会看到它。 好吧,这就是你如何欺骗一个呼叫树。 A一直花费在对C的调用上。 现在,如果相反A调用B1,B2,... Bn,并且那些调用C,则从A到C的“热路径”被分解成片段,因此A和C之间的关系被隐藏。 还有许多其他非常普通的编程实践会混淆这些工具,特别是当样本深度为10-30级且功能都很少时,但是这些关系无法避免程序员仔细检查中等数量的样本。
答案 1 :(得分:2)
我同意Mike的回答:调用图不是检查问题根源的正确方法。你真正想要的是查看最热样本的调用链。
如果您不想“手动”检查oprofile收集的原始样本,您可以使用perf的record
命令使用-g选项重新运行您的应用程序以便收集堆栈跟踪。然后,您可以使用perf的report
命令显示使用callchains注释的样本。由于perf没有在全局调用图中聚合各个样本的调用链,因此您没有Mike的帖子中列出的一些问题。