在剖析(profile)的语境中,什么是安全点(safe points)和安全点轮询(safe point polling)?

16

我遇到了这样的情况:我看不到某些方法调用没有VisualVM应用程序记录下来。想找出原因,我找到了这个SO上的答案。第三点提到了采样方法可能存在潜在问题(这似乎是唯一一个选项,因为我正在进行远程分析)。它提到了代码中的安全点和代码本身对安全点轮询的问题。这些术语是什么意思?

2个回答

11

关于Java采样分析工具的不准确性问题及其与安全点的关系,在评估Java分析器的准确性(PLDI'10)中有很好的讨论。

基本上,由于采样发生在安全点期间,因此Java分析器可能会产生不准确的结果。由于编译器可以修改安全点的出现,因此分析器可能永远不会对某些方法进行采样。因此,分析器被安排记录代码的采样(时间间隔到了),但必须等待安全点的出现。由于编译器会移动安全点,所以理想情况下应该采样的方法从未被观察到。

正如先前的答案所解释的那样,安全点是代码中的事件或位置,编译器在其中断开执行以执行一些内部VM代码(例如GC)。

安全点轮询是实现安全点或安全点触发器的一种方法。这意味着在正在执行的代码中,您定期检查标志以查看是否需要执行安全点执行,如果是(由于例如GC触发器),则线程被中断并执行安全点。请参见GC安全点(或安全区域)


1
正如我在博客上评论的那样:“Mytkowicz和Diwan的论文真的让我很困扰。例如,它对‘热点’的定义似乎意味着‘自身时间百分比’。30年前发明gprof的整个原因就是自身时间不足以作为诊断依据。另一个让我困扰的方面是它集中于方法而非代码行。还有一个问题是它对抽样统计的浅薄理解。” 有人真的读过这些东西吗?请看这里: - Mike Dunlavey

6

这篇博客文章讨论了安全点。 基本上,它们是代码中允许GC、堆栈跟踪等中断的点。

该文章还说,由于安全点会延迟堆栈采样,因此可能无法在您希望它们出现的位置出现,这是一个问题。

在我看来,这只是一个小问题。 之所以进行堆栈采样(而不仅仅是程序计数器采样),是为了展示导致当前状态的所有调用站点,因为它们很可能是比程序计数器执行更缓慢的重要源。 (如果有的话。您可能正在进行I/O,在那里PC是无意义的,但是调用站点仍然同样重要。) 如果堆栈采样必须等待几个周期才能到达安全点,那么所有这意味着它发生在一段指令块的末尾,而不是中间。 如果您检查样本,仍然可以很好地了解发生了什么。

我希望分析器编写者们意识到他们不需要过多关注细节。 更重要的是不要错过大问题。


1
基于使用两种性能分析器的经验,我不同意这种说法。一个有偏差的采样器可能会浪费你的时间在完全错误的优化上... - Nitsan Wakart
@Nitsan:你所关心的是“假阳性”——即发现了错误的问题。更大的问题是“假阴性”——即未发现真正的问题。通常的假设是,如果分析器找不到需要优化的内容,那么就没有需要优化的内容,这个假设既不是定理,也不是实践中基础良好的假设。在这里全部探讨过了我提到的方法确实有小概率出现假阳性。根据我的经验,分析器出现假阴性的概率很高。后者的代价要高得多。 - Mike Dunlavey
你的假设“堆栈示例必须等待几个周期才能达到安全点”是你的论点所依赖的。JIT编译器可以内联方法(从而在返回时移除安全点),使得在安全点之间存在大量代码。 - Nitsan Wakart
@Nitsan:没关系,因为它在程序计数器级别上。在大型软件中,调用树可能会有20-30个层级,因此这是堆栈样本的深度。如果您在>1个堆栈样本中看到堆栈上的每个调用,则可以摆脱它,这将显着提高速度,无论安全点、内联和系统阻塞如何。加速的数量显示在我的名字旁边的分布图中。 - Mike Dunlavey
1微秒是需要大量汇编代码来处理的。一个无偏的分析器在查找代码中的热点方面可以和本地分析器一样好。这样可以避免阅读大量汇编代码 :)。对于Java,有很好的分析器可用,所以如果可以选择更好的为什么不选择呢? - Nitsan Wakart
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接