OpenJDK微软版本默认启用增强型逃逸分析


OpenJDK 17.0.8 增强功能:

  • 包括一个新功能(请参阅JDK-8287061JDK-8289943),通过增加标量替换的机会数量来提高逃逸分析的性能。现在默认启用此功能。要禁用它,开发人员必须使用以下 JVM 标志:
    -XX:-ReduceAllocationMerges

逃逸分析(转义分析)
逃逸分析是一个分析过程。它检测对象在编译单元外部是否可见。
通过返回或作为参数传递给另一个方法,对象可以在编译单元外部变得可见,或写入字段。

聚合的标量替换使用转义分析的结果,并适用于未转义编译单元或仅在某些分支上转义的对象。它用简单值(标量)替换对象(聚合),其效果与局部变量类似。

逃逸分析确定可以存储对象的所有位置,
以及是否可以证明对象的生命周期仅限于当前方法和/或线程。

但是,标量替换确实是一种你永远无法绝对确定的优化,因为它取决于太多因素。

  • 首先,只有当实例的所有使用都内联在一个编译单元中时,才可以消除分配。然而,内联本身在 HotSpot 中是一种脆弱的优化,因为它依赖于许多启发式方法和限制
  • 其次,如果引用有条件地接收不同的值,则不会发生标量替换。

另一篇推荐阅读的文章是 Aleksey Shipilёv 的博客文章,其中还演示了如何使用JMH来验证标量替换是否在特定场景中发生。

网友建议:

  • 除非您是性能专家(其实很难),否则不要假设哪种代码性能良好或性能较差,并在分析探查器报告时保持怀疑态度。这不是特别有用的建议(它归结为:分析器报告可能在骗你!),但事实就是如此。实际上,要么成为性能专家,要么接受对此无能为力的事实。
  • 编写惯用的 java 代码。它最容易维护并且最有可能通过热点进行优化。
  • 降低算法复杂性是有用的,并且应该始终是您检查的第一件事。在某种程度上,降低算法复杂性的优化会忽略第一条规则。您不需要特别了解 JVMTI 或 Flight Recorder 的变幻莫测以及分析器的工作原理,就可以得出算法重写是值得的并且将显着提高性能的结论。
  • 不要相信简洁的经验法则,无论有多少人这么说。不要寻找“易于应用的模式”,例如“通过附加先测试空的 if 块来替换所有 foreach 循环”——这些本质上永远不会正确,并且通常会降低性能。