微软OpenJDK引入实验性功能以改进逃逸分析

Microsoft 发布 OpenJDK 实验性性能优化功能

Microsoft 宣布了一项仍在开发中的实验性功能,该功能通过增加标量替换(Scalar Replacement)的机会来提升逃逸分析(Escape Analysis)的性能。目前,该功能仅在Microsoft Build of OpenJDK中可用,但未来可能成为 OpenJDK 的一部分。

功能启用方式

该功能可以通过以下 JVM 标志在 Microsoft Build of OpenJDK 11 和 17 中启用:

-XX:+UnlockExperimentalVMOptions -XX:+ReduceAllocationMerges

逃逸分析与标量替换

逃逸分析由 Java 运行时(具体为 JIT 编译器)执行,用于检测仅在方法内部使用的对象。通常情况下,对象会在堆上分配内存,但如果对象未逃逸出方法(即未返回给其他方法使用),JVM 可以将其分配在栈上,类似于自动栈分配。这种方式在方法返回后会自动释放内存,无需垃圾回收器管理。

HotSpot VM 源代码文件 escape.hpp 描述了对象的处理方式:

typedef enum {
    UnknownEscape = 0,
    NoEscape      = 1, // 对象未逃逸方法或线程,且未传递给调用。可被标量替换。
    ArgEscape     = 2, // 对象未逃逸方法或线程,但作为参数传递或被引用,且在调用期间未逃逸。
    GlobalEscape  = 3  // 对象逃逸方法或线程。
}

其中,NoEscape 表示对象可以被标量替换。标量替换将对象的字段提取为方法内的局部变量,JIT 编译器可以将其存储在 CPU 寄存器或栈上。

功能改进与性能提升

该实验性功能通过简化对象分配合并来提升标量替换的效率。JDK 11 包含简化版本,而 JDK 17 能够执行更多的标量替换。

在 JDK 17 中启用该功能后,Microsoft 观察到标量替换增加了 3% 到 8%,内部基准测试的吞吐量提升了 2%。在 JDK 11 中启用该功能后,内存密集型应用的平均 P99 延迟降低了 8%

开发者贡献与代码变更

Microsoft 开发者 Cesar Soares 在 OpenJDK GitHub 仓库提交了 pull request,详细描述了该功能的实现。相关的代码变更可以在 GitHub 上查看:

该功能在 GitHub 上进行了详细讨论与审查。

阅读 33
0 条评论