关于HotSpot动态反优化

8
当我阅读《Scala in depth》这本书时,它提到了HotSpot编译器有几个重要的特性之一是“动态去优化”:
它的能力在于确定一个优化实际上并没有改进性能,并撤销该优化,从而允许应用其他优化。
看起来HotSpot会尝试各种“优化”,并选择最好的一个。但我并不太理解。这里的“优化”是否都由HotSpot提供?我的意思是程序员经常使用一些技巧来优化代码,HotSpot会处理它们吗?
还有,HotSpot会尝试哪些常见的“优化”呢?
3个回答

11
Oracle提供了JVM应用这些性能技巧的(相当简洁)总结。它解释道:

反优化是将优化的堆栈帧更改为未优化的过程。就编译方法而言,它也是抛弃具有无效乐观优化的代码并用不太优化但更健壮的代码替换它的过程。一个方法原则上可以被反优化多次。

在这个总结中,反优化的原因列举如下:

  1. 编译器可能会将未执行的分支截断并进行去优化,如果该分支被执行,则会触发去优化。
  2. 类似地,对于历史上从未失败过的低级别安全检查也是如此。
  3. 如果调用点或转换遇到意外类型,则编译器会进行去优化。
  4. 如果加载了一个无效的类层次结构分析的类,则任何受影响的方法激活都将被强制到安全点并进行去优化。
  5. 这种间接的去优化是通过依赖系统来实现的。如果编译器做出了未经检查的假设,则必须注册可检查的依赖项。(例如,类Foo没有子类,或者方法Foo.bar没有重写。)

就个人而言,我认为微基准测试方面的这篇博客文章很易读,它还涵盖了HotSpot VM上优化和去优化的主题。此外,我还推荐阅读这个演示文稿


10

HotSpot的优化与开发人员在Java源代码级别所做的优化不同,尽管其中一些具有相同的净效应。

这是JIT编译器的武器库之一:

  • 方法调用内联;
  • 从循环中提取值;
  • 单态调用点;
  • 对象根据逃逸分析放置在堆栈上;
  • 将变量绑定到CPU寄存器;
  • 锁消除。

最有趣的部分是某些优化之间的协同作用,例如:

  1. 调用点作为单态实现;
  2. 这允许方法内联;
  3. 这引导对象的堆栈放置;
  4. 这允许将对象字段绑定到寄存器。

然而,据我所知,你引用的内容是错误的。优化后的代码不会进行任何自我剖析,因为这会使其变慢。反编译的唯一条件是违反 JIT 编译时的乐观假设。例如:给定一个方法调用站点只接收一种类型的对象,并专门为该对象进行编译(编译为单态调用站点),但随后出现了不同的对象类型。现在,无法执行优化后的代码,必须进行反优化。


0

"编译器优化"是对代码的转换,旨在以某种方式使其更好 - 通常是让它执行所需时间更短。 维基百科关于优化编译器的文章列出了常见的优化技术清单;Hotspot JIT编译器可能会应用所有这些技术和更多。

因此,该书意味着Hotspot将对代码应用一些技术,看看是否改善了运行时,如果没有,就会恢复原样。

正如您正确指出的那样,通过手动更改代码使其更好的过程也称为“优化”或“手动优化”。编译器尝试应用尽可能多的优化,但仍需要手动应用许多可能的修改。再次提醒,维基百科有一篇关于程序优化的扎实文章


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