GraalVM免费新版本提供了原生镜像G1等收费功能


GraalVM(Java VM)刚刚发布了一个新的发行版--免费提供了一些商业版本的功能。这意味着-您现在可以在生产环境中免费使用这些GraalVM功能! 太棒了!

新的发行版Oracle GraalVM,适用于JDK 17和JDK 20,并在GraalVM免费条款和条件(GFTC)许可下发布(也见FAQ)。这意味着你可以免费使用所有最伟大的GraalVM商业收费功能,无论是用于开发还是用于生产!

对于Native Image原生镜像,在这个版本中,我们将引入:

  • 配置文件指导下的优化和更多的编译器优化,以获得最佳的峰值性能
  • G1 GC用于运行具有大堆和最小暂停时间的应用程序
  • 压缩对象头和指针,以达到更低的内存占用率
  • 机器学习,自动推断剖析信息
  • 支持SBOM的额外安全功能

GraalVM Native Image已经因其即时启动而闻名,但通过这个版本,我们可以证明,它也是一种令人难以置信的高效方式,可以高性能地运行长期运行的Java应用程序。

我们在一个用GeralVM Native Image编译的Java 20 Spring PetClinic示例应用程序上测试了我们的版本,并与JIT编译进行了比较,其性能优势如下:

Native Image原生镜像以最快的应用程序启动时间而闻名。由于有了Oracle GraalVM的额外编译器优化,启动速度更上一层楼:

  • 与GraalVM CE Native Image相比,Oracle GraalVM Native Image的启动速度提高了46.42%。
  • 与在JIT上运行相比,启动速度快32倍(GraalVM CE与C2 JIT)。

由于额外的内存优化,我们用Oracle GraalVM Native Image构建的基准应用程序使用的内存明显减少:

  • 比使用GraalVM CE Native Image少25%的内存
  • 比使用C2 JIT的GraalVM CE少2.52倍的内存!

Oracle GraalVM Native Image的峰值吞吐量比GraalVM CE高1.6倍。对于这个特定的应用,吞吐量仍然略低于JIT。当用Spring以及Quarkus和Micronaut运行其他基准时,在许多情况下,我们看到AOT的峰值吞吐量甚至超过了JIT。

对你的应用程序进行评估的另一个重要指标是效率:在给定的时间和资源下,你能获得多少性能。这与云计算特别相关,在那里你为资源和你使用它们的时间付费,但即使在内部,你也想有效地使用你的基础设施。

Oracle GraalVM Native Image可以处理14780个请求/GB/s,是CE Native Image和C2 JIT的两倍。

这意味着使用Oracle GraalVM Native Image,你可以为你所拥有的基础设施获得最佳的峰值吞吐量,或者即使在资源有限的环境中也能以良好的性能运行。

现在让我们来看看延迟情况。
延迟是一个重要的指标,反映了你的应用程序的所有请求的响应能力。最慢的请求在尾部延迟分布中可见,并对服务质量产生很大影响。通常情况下,业务需求对大多数请求规定了特定的延迟限制(通常是99%,即P99延迟)。

Oracle GraalVM Native Image和CE JIT与C2的响应时间非常相似,都在3ms以下。
这意味着你可以期望你的应用程序在Native Image和JIT上有同样的响应能力。
然而,在JIT上最高的百分位数明显下降,而在Native Image上则保持较低的水平。所以对于这个应用来说,Native Image提供了一个明显更好的P99延迟,从而改善了服务的响应性。

总之,Oracle GraalVM Native Image除了快速启动和低资源使用外,还为长期运行的应用程序提供了出色的性能特征。

适用于JDK 17和JDK 20的GraalVM
GraalVM现在有一个新的命名方案,与JDK的版本划分相一致--例如,这个版本包括两个GraalVM版本:GraalVM for JDK 17 和 GraalVM for JDK 20。这两个版本都是基于主分支的,都包含新的功能,所以你可以选择最适合你的JDK版本。

不过,我们鼓励你转到JDK 20--正如我们前段时间宣布的那样,我们正在过渡到一个新的发布时间表,我们将只为最新的Java版本发布GraalVM(就像Oracle JDK那样)。这样一来,你也可以同时使用所有最新的Java和GraalVM功能。

这个版本的另一个伟大的更新是,GraalVM JDK的下载现在包括了Native Image!不需要将Native Image作为一个单独的组件下载,也不需要运行gu install native-image,它从一开始就已经准备好了。

下载Oracle GraalVM也变得更容易了--我们现在有了稳定的可编写脚本的下载URL,所以你可以直接使用它们来下载,或者在你的脚本和Docker文件中使用。例如,要在Linux x86-64上获得适用于JDK 20的Oracle GraalVM,请运行以下命令:

wget https://download.oracle.com/graalvm/20/latest/graalvm-jdk-20_linux-x64_bin.tar.gz

用于编译器优化的机器学习
Oracle GraalVM中的一个非常有用的功能是剖析引导的优化(PGO)。PGO使你能够在运行时收集应用程序的剖析信息,然后与Native Image一起使用,以优化生成的本地可执行文件的性能。它使你能够结合两个世界的优点:AOT优化和运行时剖析的力量。

这个版本中令人激动的新功能之一是基于机器学习的配置文件推断。Native Image现在使用一个预先训练好的ML模型来预测控制流图分支的概率。然后,我们使用预测的概率来执行PGO。在我们对Renaissance、Da Capo和Da Capo con Scala等综合基准的测量中,与默认的Native Image配置相比,由预测的配置文件驱动的PGO提供了6%的运行时速度提升。基于ML的配置文件推断在Oracle GraalVM中是可用的,默认情况下是启用的,我们期待着您的反馈和性能报告。

然而,请记住,ML配置文件推断可能会使本地可执行文件的大小略微增加1-2%。

原生镜像中更多的性能
编译器可以提供更好的性能,其中一个方法是利用你的部署平台的特定架构功能。使用这些特定的功能对性能是很好的,但在没有这些特定指令的机器上部署时,可能会带来兼容性的挑战。我们引入了一个新的-march选项,类似于gcc,让你可以在特定平台的性能和兼容性之间灵活选择:-march=compatibility可以获得最佳的兼容性,或者-march=native可以获得最佳的性能,如果本地可执行文件被部署在相同的机器架构上或具有相同CPU特性的机器上。要列出所有可用的机器架构,使用-march=list。

我们还对配置文件引导的优化做了一些改变:

  • 为了给您的应用程序提供最佳的峰值性能,PGO必须拥有其完整的剖析信息。这意味着您可能需要在不同的工作负载下多次运行您的应用程序,以确保对其所有的使用情况进行分析。现在,在PGO多次运行中收集的剖析信息可以与本地镜像配置合并。
  • 剖析引导的优化现在有一个新的采样剖析器,可以收集调用堆栈。这些数据会被包含在一个.iprof文件中。构建PGO指导下的可执行文件时,默认开启采样分析器(但必要时可以禁用)。请记住,为了获得良好的剖析,从而获得良好的峰值性能,你需要运行相关的工作负载并适当预热你的应用程序。
  • 我们还实施了一个上下文感知的inliner优化,它使用新的采样剖析器来更好地将优化努力投入到热代码中。其结果是,可执行文件的大小减少了2-7%,峰值性能有所提高。
  • 我们改进了对Native Image的循环矢量化支持,使编译器能够矢量化更多的循环以加快执行速度,并使AOT中某些代码形状的性能与JIT相当。

原生镜像包
Native Image原生镜像 构建命令 (native-image -jar MyApp.jar) 表面上看起来很简单,但它启动了一个复杂的构建过程,其中有许多取决于环境的变量和属性。能够复制一个构建过程是非常有帮助的--例如,用于更新和修补你的应用程序,或者重现问题。为了这个目的,这个版本引入了本地镜像包。

现在你可以生成一个构建包,其中包含你的应用程序的JAR文件,以及参数、环境变量、系统属性设置、classpath和模块路径选项等信息。

要产生一个捆绑包,在构建本地可执行文件时使用 - bundle-create=<imagename>.nib 标志。
这将产生实际的可执行文件,就像以前一样,还有一个<imagename>.nib文件和<imagename>.output目录。

有了这些文件,你就可以通过运行以下程序来复制构建:

native-image -bundle-apply=.../path/to/<imagename>.nib

捆绑程序应该可以简化更新Native Image的部署,并有助于调试和重现问题。

原生镜像Native Image的开发者体验
每一次发布,我们都会引入更新,使开发者在使用GraalVM,特别是Native Image时的体验更加流畅和精简。在这个版本中,有几个变化:

  • 改进了Native Image构建过程中的内存占用率。构建器现在考虑到了可用的内存,以减少在同一台机器上运行许多其他进程时的内存压力。在许多情况下,它消耗的内存也更少,因此也更不可能因内存不足的错误而失败。同时,我们增加了Native Image可以使用的最大内存量,这将有助于构建大型应用程序。
  • 对我们的Windows用户来说是个好消息!Native Image现在可以自动为Windows设置构建环境--你不再需要使用x64 Native Tools命令提示符。我们还改进了在Windows上的调试:调试信息现在包括Java类型的信息。
  • 我们继续建立我们的JFR支持。现在也支持以下事件:ExecutionSample、ObjectAllocationInNewTLAB和JavaMonitorInflate。
  • 我们致力于使元数据构成安全,这样添加新的元数据就不会破坏构建。
  • 内部错误变得更加用户友好。在失败的情况下,Native Image的构建不再只是显示堆栈跟踪,而是提供一个错误报告和如何报告这个问题的说明。
  • 现在可以通过LLVM后端在RISC-V上使用GraalVM Native Image了

原生镜像的新监控功能 
应广大用户的要求,我们和社区一起通过JMX实现了远程管理。

​​​​​​​它可以通过 --enable-monitoring选项启用,例如: --enable-monitoring=jmxclient,jmxserver。

注意,这个功能是试验性的。