【译】Oracle GraalVM 发布,启动快了46.42%
一、Oracle GraalVM
Oracle GraalVM 是一个新 GraalVM 的发行版,它适用于JDK 17和JDK 20,并在GraalVM 免费条款和条件(GFTC)许可证下发布(请参见FAQ)。这意味着你可以免费使用所有最优秀的GraalVM功能,无论是在开发中还是生产环境!
对于Native Image,在这个版本中引入了以下特性:
Profile-guided 优化 和更多编译器优化,以获得最佳的峰值性能 G1 GC用于运行具有大堆和最小暂停时间的应用程序 压缩对象头和指针,以获得更低的内存占用 机器学习自动推断分型信息 支持SBOM的附加安全功能
GraalVM Native Image 已经因其即时启动而闻名,但是随着这个版本的发布,我们可以展示它也是一种非常高效的方式来运行长时间运行的Java应用程序,且性能高。我们已经在使用GraalVM Native Image编译的一个Java 20 Spring PetClinic 示例应用程序上进行了测试,并与JIT编译进行了比较,以下是性能结果:
使用 Oracle GraalVM Native Image、GraalVM CE Native Image 和带有 C2 JIT 的 GraalVM CE 的 Spring Petclinic 性能。基准测试实验在 Oracle X5-2 服务器(Intel Xeon E5-2699 v3)上运行了最新的 Spring Petclinic,将工作负载限制在16个CPU,并设置了最大堆大小为1GB。使用wrk测量最大吞吐量,以循环方式击中五个不同的端点(创建宠物、所有者和诊所访问并读取所有者和宠物ID),每秒600个请求,在100秒内进行。峰值吞吐量是以下180秒的平均性能。延迟数字是在吞吐量实验完成后捕获的,使用 wrk2应 用每秒5000个请求的恒定负载。
现在让我们更仔细地看一下这些性能指标。
Native Image 以启动速度快而闻名。由于使用 Oracle GraalVM 的额外编译器优化,启动将提升到一个新的级别:
相对于GraalVM CE Native Image,Oracle GraalVM Native Image的启动速度**快46.42%**。 启动速度比在JIT上运行(GraalVM CE with C2 JIT)快32倍。
由于使用了额外的内存优化,使用 Oracle GraalVM Native Image 构建的应用程序使用内存显著减少:
相对于GraalVM CE Native Image,少25%的内存。 相对于GraalVM CE with C2 JIT,少2.52倍的内存!
在这里,Oracle GraalVM Native Image 的峰值吞吐量比 GraalVM CE 高 1.6 倍。对于这个特定的应用程序,吞吐量仍略低于 JIT。当在 Spring、Quarkus 和 Micronaut 等其他基准测试中运行时,在许多情况下,我们看到 AOT 在峰值吞吐量方面甚至领先于JIT。
另一个评估您的应用程序重要的指标是效率:在给定的时间和资源量下可以获得多少性能。这在云端尤为重要,因为您需要支付资源的费用以及使用它们的时间长度,但即使在本地环境中,您也希望高效地利用基础设施。为了评估这一点,让我们看一下我们的应用程序可以每秒处理多少个请求,每GB内存(参见上图):
Oracle GraalVM Native Image 可以每秒处理 14780 个请求/GB/s,是CE Native Image 和 C2 JIT 的两倍。
这意味着使用 Oracle GraalVM Native Image,您可以获得适合您基础设施的最佳峰值吞吐量,或在资源受限的环境中实现良好的性能。现在让我们来看一下延迟分布。延迟是反映应用程序所有请求响应能力的关键指标。最慢的请求在尾延迟分布中可见,并且极大地影响着服务质量。通常,业务需求规定大多数请求的特定延迟限制(通常是99%,即P99延迟)。
在这里,我们可以看到在95个百分位之前,Oracle GraalVM Native Image 和 CE JIT with C2 有着非常相似的响应时间,均低于3毫秒。这意味着您可以期望使用本地镜像与JIT相同的应用程序响应性。然而,在最高百分位数上,JIT 的响应时间明显下降,而 Native Image 的响应时间保持较低。因此,对于这个应用程序来说,Native Image 提供了明显更好的 P99 延迟时间,因此提高了服务的响应性。综上所述,Oracle GraalVM Native Image 为长时间运行的应用程序提供了出色的性能特征,同时具有快速启动和低资源使用的优点。我们还在此版本中推出了许多新功能。由于更新涵盖范围广泛,我们发布了两篇博客文章:本篇博客侧重于 GraalVM JDK 和 Native Image,另一篇则涵盖了 GraalVM 语言和 Truffle 的更新。现在,让我们看看此版本中还有什么新内容!
二、基于 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 等全面基准测试中,由预测配置文件推动的 PGO 相比于默认的 Native Image 配置可提供约 6% 的运行时加速。基于 ML 的配置文件分析在 Oracle GraalVM 中可用,并默认启用,我们期待您的反馈和性能报告。但是,请记住,ML 配置文件推断可能会略微增加本地可执行文件的大小,约1-2%。
四、更高性能的 Native Image
编译器提供更好性能的一种方式是利用部署平台的体系结构特定功能。使用这些特定功能可以提供更好的性能,但在部署到没有这些特定指令的机器上时可能会出现兼容性挑战。我们引入了一个新的 **-march** 选项,类似于gcc,它可以让您在平台特定性能和兼容性之间进行选择:-march=compatibility 提供最佳兼容性,或者 -march=native 提供最佳性能,如果本地可执行文件部署在相同的机器架构或具有相同CPU特性的机器上。要列出所有可用的机器架构,请使用 -march=list。我们还对基于配置文件的优化进行了几个更改:
为了为应用程序提供最佳的峰值性能,PGO需要完整的剖析信息。这意味着您可能需要多次运行您的应用程序,并使用不同的工作负载来确保所有的用例都被剖析。现在,通过 native-image-configure可以合并多次PGO运行收集的剖析文件。基于配置文件的优化现在有一个新的采样分析器,可以收集调用堆栈。此数据随后包含在一个.iprof文件中。当构建有PGO仪器的可执行文件时,默认情况下启用采样分析器(但必要时可禁用)。请记住,为了获得良好的配置文件,从而获得良好的峰值性能,您需要运行相关的工作负载并正确地预热应用程序。 我们还实现了一个上下文感知内联器优化,它使用新的采样分析器将优化工作更好地投入到热代码中。结果是2-7%更小的可执行文件大小和增加的峰值性能。 我们改进了Native Image的循环向量化支持,允许编译器向量化更多的循环以实现更快的执行,并将某些代码块在 AOT 上的表现与 JIT 相媲美。
五、Native Image Bundles
表面上看,Native Image 构建命令(native-image -jar MyApp.jar)可能看起来很简单,但它启动了一个复杂的构建过程,有许多变量和属性依赖于环境。如果能够复制构建过程,例如用于更新和修复应用程序,或者重现问题,将非常有帮助。为此,这个版本引入了 Native Image Bundles。现在,您可以生成一个构建捆绑包,其中包含应用程序的 JAR 文件以及有关参数、环境变量、系统属性设置、类路径和模块路径选项的信息。要生成捆绑包,请在构建本地可执行文件时使用 — bundle-create= 文件和 目录。有了这些文件,您可以通过运行以下命令来复制构建过程:native-image -bundle-apply=…/path/to/捆绑包应该简化更新 Native Image 部署,并有助于调试和重现问题。请尝试使用这个功能,并让我们知道您的想法!
六、Build 构建报告
Native Image 现在可以生成构建报告,帮助您更好地了解可执行文件的内容。构建报告以 HTML 格式展现,并提供以下信息:
构建环境和使用资源的信息 包括可达类型、字段和方法在内的分析结果 代码和堆区域的完整分解 软件材料清单(SBOM)
构建报告摘要和代码区域分解使用 -H:+BuildReport 开启这个实验性功能。
七、Linux 下的 AWT
我们已经在 Native Image 中改进了 AWT 支持:除了 Windows 之外,它现在还可以在 Linux 上工作!这意味着更多的 GUI Java 应用程序现在可以在 Native Image 上运行。我们期待着看到您的应用程序使用 Native Image 运行并收到您的反馈。改进的 AWT 对于 macOS 的支持也正在路上。
一个使用 GraalVM 构建的 Linux 原生可执行 AWT 应用
八、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 —— 在相关博客文章中阅读更多信息。
九、新的 Native Image 监控功能 📈
受社区的强烈要求,我们实现了 JMX 远程管理功能。它可以通过 --enable-monitoring选项进行启用,例如:--enable-monitoring=jmxclient,jmxserver。请注意,此功能仍处于实验阶段。
十、开始 Native Image ✅
我们经常会听到这样一个问题:“我怎样才能知道是否可以使用 X 库与 Native Image 一起使用”。现在在 graalvm.org 上,您可以找到一份经过测试并可与 Native Image 完美配合的库和框架列表。目前,该列表包含了150多个经过验证可以与 Native Image 一起使用的库和框架,包括 Micronaut、Spring、Quarkus、Helidon、H2、GraphQL、MariaDB、Netty、MySQL、Neo4j、PostgreSQL、Testcontainers、Thymeleaf 等等。我们很高兴看到我们的生态环境积极采用 Native Image,并通过GraalVM-reachability-metadata 仓库提供支持。这个仓库也与 Native Build Tools 集成在一起,因此现在可以自动发现和拉取依赖项的 Native Image 配置文件。
十一、GraalVM JDK 和编译器更新
GraalVM JIT 现在已经支持 ZGC!ZGC 是一个低延迟的垃圾收集器,面向需要低延迟或大堆大小的应用程序。(目前,在 Native Image 中不支持 ZGC。)要启用它,请使用命令行选项 -XX:+UseZGC。我们预计这个更新对于大型应用程序或低延迟至关重要的情况将有所裨益,并期待您的反馈和性能报告。 我们还正在开源 Ideal Graph Visualizer(IGV)!🎉 IGV 是一款开发人员工具,可让您分析编译图并调查性能问题。我们希望 IGV 对于那些在 GraalVM 之上实现语言或调查高级编译问题的人特别有帮助。
十二、社区贡献
graalvm-reachability-metadata 仓库共收到近200个社区贡献,使Java库能够在Native Image中使用。我们特别感谢 Spring 和 Micronaut 团队的大力支持。 我们与 Red Hat 一起继续构建 JFR 支持、改进 Windows 上的调试,并添加了实验性的 JMX 支持。 您提供的所有反馈、性能基准和问题报告都有助于我们在每次发布时进一步改进 GraalVM。
十三、GraalVM 生态有什么新功能
我们基于社区调查的回答,发布了一份GraalVM生态系统的大概述:最常用的功能和工具、库和框架的采用情况、编程语言等等:GraalVM 社区 2022 调查报告【译】。 Spring Boot 发布了支持 Native Image 的主线版本 Spring Boot 3.0 !📦 Quarkus发布了带有许多新功能的 Quarkus 3;我最喜欢的可能是新的改进和可扩展 Dev UI —— 试试吧! Micronaut 将很快发布4.0版本,使用 Java 17 作为基线,并提供更快的构建方式 —— 您已经可以尝试 Milestone 2 了。 现在您可以使用 Azure App Insights 监控 GraalVM 和 Spring Boot 应用程序。 Testcontainers 通过 GraalVM Reachability 仓库与 Native Image 一起工作,还有几个框架提供平稳的集成 —— 例如看看 Micronaut 如何在Native Image 和 JVM 模式下测试 RabbitMQ 集成。 Ionut Balosin 和 Florin Blanaru发布了一份独立(非常详细)的 GraalVM 与 OpenJDK C2 性能研究。 我们还看到了关于 Apache Kafka、Quarkus 和 GraalVM 的有趣实验:单个代理节点运行需要约 130 毫秒,并且具有 60MB 的 RSS。
