一、前言

GraalVM 21.2 曾经公布,在这篇文章中,咱们将重点介绍这个版本中最显著、最重要、最令人兴奋的更新。

首先,GraalVM 21.2版本可从下列中央下载:

  • GraalVM
  • GraalVM Enterprise

GraalVM 由几个组件组成,在每一个版本中,咱们都在致力改良它们。因而,如果你对某个特定组件感兴趣,并心愿取得更改的更具体概述,请参阅文档。

二、Native Image

让咱们先从 Native Image 中值得注意的新内容开始。早在6月份,咱们就为 Native Image 公布了新的 Gradle 和 Maven 插件,并且提供了最后的 JUnit5 的反对。它简化了构建你的应用程序的 Native Image 的过程,并且容许用 JUnit 的形式在 Native Image 模式下测试你的代码运行状况。


图示:在 native image 模式下运行JUnit测试时的Gradle输入示例。

从最后的版本公布以来,曾经有两个小版本对各种 bug 进行了修复,改良和清理,所以如果你保护了一个应用 Native Image 的应用程序或库,思考运行这两个测试去验证在 Native Image 中的运行状况!

另一个改良是当初 Native Image 会主动从 image 中删除不必要的 security providers,这些能够被拜访的security providers 会被动态分析程序检测。这意味着像 --enable-all-security-services 之类的参数会被弃用,并且在将来会被移除。也能够应用 -H:-EnableSecurityServicesFeature 齐全禁用自动检测并手动注册provider。你能够从这个文档中理解到更多细节.

21.2 中一个十分受欢迎的新增性能是实现 class 预约义,以反对运行时的 ClassLoader.loadClass 调用。 须要在运行时加载的所需 class 必须在构建时提供给动态剖析,以便将它们蕴含在关闭世界中剖析,蕴含在运行时任意时刻加载类的代码模式当初能够在 native images 中工作,正如您所冀望的那样。

GraalVM 21.2 的另一个乏味的根底加强是应用-H:+AllowVMInspection构建的 Native Images 当初反对用Java 编写 JFR 事件。 要在运行时记录 JFR 事件,必须应用命令行选项-XX:+FlightRecorder-XX:StartFlightRecording来启用 JFR 反对和 JFR 记录。 理论须要实现的事件并不多,但实现它们或从利用程序代码收回它们的体系结构是可用的。

你能够尝试以下示例来查看自定义事件在实践中的成果:

import jdk.jfr.Event;import jdk.jfr.Description;import jdk.jfr.Label;public class Example {    @Label("Hello World")    @Description("Helps programmer getting started")    static class HelloWorld extends Event {       @Label("Message")       String message;    }    public static void main(String... args) {       HelloWorld event = new HelloWorld();       event.message = "hello, world!";       event.commit();    }}

将其构建到本机映像中,应用 -XX:+FlightRecorder -XX:StartFlightRecording=”filename=recording.jfr” 运行,你能够在 VisualVM 中看到事件的样子:

三、编译器更新

每次更新都会在编译器中带来增量的改良和新的优化,从而减少一些工作性能。随着工夫的推移,这些收益积攒起来,并导致显著的性能晋升。如果你最近没有更新,当初是利用所有这些改良的好时机。在21.2中,向编译器增加了许多乏味的优化。让咱们从GraalVM Enterprise中可用的组件开始,它们是Oracle Java SE订阅的一部分。

咱们改良了计数循环的循环限度剖析,因而编译器还剖析循环前的控制流,以推断演绎变量。 这能够产生更多的未计数循环,就像上面的例子一样,可用于高级优化

long i = 0;if (end < 1) return;do {    // body    i++;} while (i != end);

在这里,编译器能够联合循环之前i0end ≥ 1的信息来证实end > i并应用该数据来优化循环体。

咱们还为非计数循环增加了一种新鲜的条带开掘优化,它将循环迭代拆分为多个局部,使它们更易于当前优化。 默认状况下是禁用的; 应用-Dgraal.StripMineNonCountedLoops=true选项启用它。

咱们改良了应用 StringBuilder 模式的代码的编译,并通过使基于 JDK11 的 GraalVM 构建晓得JDK11 中的紧凑字符串来加强对这些模式的反对。

而后就 GraalVM 社区版而言,编译器的一个显着改良是减少了Speculative Guard Movement优化,它试图将循环不变爱护(例如:数组边界查看)从循环外部挪动到循环内部。这能够显着改善相干工作性能。

此外,咱们改良了long计数循环中的平安点打消机制。 编译器当初能够打消具备long演绎变量的循环中的平安点,它能够动态证实演绎变量的范畴是Integer.MAX_VALUE - Integer.MIN_VALUE。 思考这个 for 循环示例:

for (long i = Integer.MIN_VALUE;i< Integer.MAX_VALUE;i++) {// body}

编译器当初能够动态证实i只在整数范畴内迭代,即便它是一个long整数。 因而,不须要思考整数溢出的状况,循环的优化成果更好。

除此之外,此版本中还有一些可用的优化在默认状况下尚未启用,并且被认为是实验性的。 一项名为Write Sinking的实验性优化尝试将写入移出循环。 你能够应用-Dgraal.OptWriteMotion=true启用它。 GraalVM Enteprise 中提供的另一个优化(默认状况下尚未启用)是针对程序代码的新鲜 SIMD(单指令多数据)矢量化优化。 你能够应用-Dgraal.VectorizeSIMD=true选项进行试验。 如果你还没有筹备好本人进行试验,请持续关注 在行将公布的独立文章中,咱们将具体探讨它给你带来了什么,以及你的代码如何从中受害。

四、多语言和Truffle框架

Truffle 受到了一个新的编译队列启发,默认状况下启用。 这种新的启发式改良了多语言运行时在工作性能上的预热工夫。

上面简要解释一下它的作用:假如以下合成的 JavaScript 代码是你的应用程序。 循环运行2个函数,都达到了JIT编译的阈值,须要编译:

function lowUsage() {    for (i = 0; i < COMPILATION_THRESHOLD; i++) {        // Do something    }}function highUsage() {    for (i = 0; i < 100 * COMPILATION_THRESHOLD; i++) {        // Do something    }}while(true) {    lowUsage();    highUsage();}

在以前的 GraalVM 版本中,优先编译的算法是按先到先得的程序工作的。 这将导致首先编译lowUsage函数,而不是先编译highUsage的更无利的程序。

当初在 GraalVM 21.2 中,该策略比 hotness 更为简单,并思考了多层设置,更快地编译第一层,编译历史记录和勾销优化对以前确定为重要的代码进行优先级排序,以及代码 hotness 和同时应用活跃度的加权组合。 总而言之,这应该会为所有 GraalVM 语言带来更好的预热。

有额定的配置选项来调整启发式或齐全禁用它的应用。 在文档中理解更多信息。

另一个变动是嵌入多语言上下文时的某些 API 调用须要新版本的JVMCI,即用于将编译器插入 Java HotSpot VM 的编译器接口。 所有 JDK 版本的 GraalVM 发行版都蕴含新的 JVMCI,但如果你应用具备不同 JDK 的 GraalVM 语言并在模块门路上启用 GraalVM 编译器,请确保应用以下蕴含JDK-8264016的 JDK 版本,保障齐全的兼容性。

否则应用强制上下文勾销 (Context.close(true)) 或中断 (Context.interrupt(Duration)) 将抛出谬误。 为了获得最佳体验,请思考应用 Graa lVM 发行版来运行你的应用程序或防止应用这些 API。正文中形容了其余可能的解决办法。

既然咱们正在探讨的是与 Truffle 相干的更改,因而 GraalVM 21.2 中有一些令人兴奋的更新,用于在 GraalVM 上实现语言和工具的我的项目。 Truffle 库当初能够在无需当时执行的状况下为提前编译做好筹备。 无关更多详细信息,请参阅 ExportLibrary.useForAOT 和 AOT 教程。

五、JavaScript

JavaScript 实现持续增加和更新最新提案的实现,如新的 Set 办法、试验运算符重载反对或 RegExp 匹配索引提案。 你能够在发行阐明中找到无关如何启用这些性能的详细信息。

最重要的是,Graal.js 通过在多语言Context跟踪未解决的 promise rejections 选项来加强开发体验。 默认状况下,该选项设置为none,并且不会跟踪未解决的 promise rejections,然而你能够应用js.unhandled-rejections选项进行配置,并使你的开发更轻松。

六、Ruby

Ruby 也判若两人地经验了一系列继续一直的兼容性和性能改良。 一个十分有影响力的附加性能是通过应用每个名称和每个类的假如来准确地使 Ruby 办法和常量生效。 在加载 Ruby 代码时,因为 Ruby 的语义,会一一增加办法,在加载文件时会执行大量的代码。 依据每个类的假如(这是它在此更改之前在其余 Ruby 实现和 TruffleRuby 中的行为形式),它将使所有调用该类办法的调用站点有效。 通过准确生效,它只会使下一次调用实际上须要调用另一种办法的调用站点生效。 这改善了事实世界代码的预热。

随着这些更改,咱们更新到了 Ruby 2.7.3,除了 resolvstdlib 没有更新(2.7.3 中的 resolv 有bug)。 咱们还增加了一个新的TruffleRuby::ConcurrentMap数据结构,用于 ruby 并发。

无关许多其余更改和修复,请查看发行阐明。

七、Python

在这个版本中,咱们实现了一个比纯 Python 版本更快的_pickle,使序列化更快。

改良了对与其余语言的互操作性的反对,使dict类型依照你冀望的形式工作,当初应用 Truffle 哈希实现。

与平常一样,很多工作都集中在性能改良上,特地是在预热和共享引擎配置期间!

还有兼容性改良。查看发行阐明或更多详细信息。

八、LLVM bitcode运行时

在21.2 中有一些与 C++ 相干的改良。 咱们修复了 LLVM 工具链在 MacOS 11.3上C工作不失常的问题。 咱们还通过跨语言互操作性增加了对 C 虚构调用的反对。

GraalVM Enterprise 中的管理模式也失去了改善。 咱们将musl libc更新到 1.2.2 版,并通过在管理模式下增加对pthreadspthread同步原语的反对,进步了与现有 native 代码库的兼容性。

九、FastR

FastR 持续致力于兼容性,在 2021-02-01 CRAN 快照中改良其对软件包的反对:

  • 测试对 3.0.1 的局部反对。
  • 对tibble 3.0.6、vctrs 0.3.6和data.table 1.13.6的次要反对。
  • 对dplyr 1.0.3、ggplot 3.3.3和knitr 1.31的反对正在进行中。

如果你对特定软件包的反对感兴趣,请分割咱们!

十、WebAssembly

你能够看到咱们对 WebAssembly 运行时许多兼容性改良和一些谬误修复,以通过对尽可能多的应用 WebAssembly 的 NPM 模块的测试。

十一、Java on Truffle

GraalVM 21.2 for Java on Truffle 中的一项重要内容是新的Hotswap 插件 API,它容许从新加载代码而无需重启正在运行的应用程序。 该 API 旨在容许框架开发人员更好地管制反馈应用程序中的更改以响应 IDE 中的源代码编辑。 它是通过设置适当的钩子来实现的,其中次要设计准则是你能够注册将在指定的 HotSwap 事件上触发的各种 HotSwap 侦听器。 例如,当某个服务提供者的实现发生变化时,它可能从新运行动态初始值设定项,运行通用后热交换回调或钩子。

最令人惊奇的是这些API由一般的 Java 调用组成——比任何基于字节码操作的解决方案更容易集成和保护。

无关更多详细信息,请查看插件 API 文档。

对 21.2 进行的另一个十分受欢迎的改良是更好的字节码调度,它能够将 Java 在 Truffle 上应用的解释器速度进步约15-30%。 解释器速度是影响应用程序预热速度的一个十分重要的因素。

21.2 还改良了 Java 在 Truffle 对象上实现Map,Map.Entry,List,IteratorIterable与其余语言(包 括 Java 主机代 码)的互操作性。

十二、工具

VisualVM 取得了许多杰出的改良,包含对JDK 17 的反对以及容许从命令行或其余内部工具管制性能。 后者能够在装置了 GraalVM 扩大的状况下实现VisualVM 和 VSCode 之间的无缝集成。 你能够增加 IDE 配置集成 VisualVM 来剖析你的应用程序。


图示:请留神左下角的 VisualVM 选项卡,其中蕴含可间接从 VS Code 执行的操作。

VisualVM 当初还能够保留来自实时 Java 过程的 JFR 记录,并且在 Profiler 选项卡中有一个新的 Lock Contention 视图。 因而,如果你当初应用 VisualVM 来满足日常剖析需要,它比以往任何时候都更加弱小。

十三、文档

最初但并非最不重要的一点是,咱们重构了官网上的 GraalVM 文档。 当初能够在GitHub 上的主我的项目中找到它。

这意味着为 GraalVM 做出奉献并改善生态系统中许多其余开发人员的生存比以往任何时候都要容易。 如果你留神到可能应用廓清或不残缺形容你最喜爱的性能或调整选项的文档,请思考分享你的专业知识并通 pull request 帮忙我的项目! 如果有疑难,这里有一个对于如何做到这一点的简短指南:参加文档奉献。

请留神,GraalVM Enterprise 文档可在docs.oracle.com上找到。

与每个版本一样,咱们要感激 GraalVM 社区的所有合作、反馈和探讨,以及分享你如何应用GraalVM。

请不要犹豫,让咱们晓得任何和所有反馈! 有多种渠道能够分割团队,抉择最适宜你的渠道:Slack、GitHub或Twitter,或者向咱们发送邮件。

译者说:

大家好,我是 如梦技术春哥(mica 开源作者)感激深夜还一起参加翻译和校对的张亚东(JustAuth 开源作者)、吴天狗、老叶等同学。咱们曾经输入和翻译了多篇 GraalVM 和 Spring Native 的文章:

文章列表

  • GraalVM 疾速参考【译】
  • t-io 之 GraalVM 本机可执行程序实战

翻译不易,请帮忙分享给更多的同学,谢谢!!!更多精彩好文,请关注我。