GraalVM 20.2.0

2020-08-19 06:24:50

最先进和最快的运行时在Java和其他JVM语言上显示了绝对出色的结果-并且可以运行用JavaScript、Ruby、R和Python等流行语言编写的程序-只是变得更好了。

今天标志着GraalVM20.2.0的发布。这是一个功能版本,它在性能、本机映像技术以及与受支持语言的兼容性方面都有了很大的改进。

一如既往,我们真诚地感谢令人惊叹的GraalVM社区的协作,感谢他们提供反馈和提出问题,感谢他们发送拉请求并谈论您如何在项目中使用GraalVM。

在这篇文章中,我们想要强调GraalVM20.2.0中一些最值得注意的变化。有关更详细的列表,请查看网站上的发行说明。

在每个版本中,每个GraalVM组件都有许多修复和改进。编译器也不例外。让我们看看您可以在GraalVM 20.2.0中试用的两个新功能:

在GraalVM Enterprise中,当应用程序进入稳定阶段且编译空闲时,libgraal使用的内存现在将释放给操作系统。这是通过将每个编译器线程附加到库隔离来实现的。可以附加到隔离的编译器线程数由jvmci.ThreadsPerNativeLibraryRuntime系统属性控制。默认值为附加到单个隔离的所有线程。隔离是按需初始化的,以处理额外的编译器线程。当编译器线程变得空闲(可通过jvmci.CompilerIdleDelay系统属性配置)时,它会将自己从隔离中分离出来。当最后一个线程从隔离区分离时,隔离区被关闭,其内存(即,库堆)释放给操作系统。此功能有许多优点:

它可以减少GraalVM进程的RSS内存占用。如果未使用编译器,则不使用任何资源。

如果使用多个隔离,则可以减轻编译器线程之间的干扰。例如,共享对象上的争用较少,一个隔离中的垃圾回收不会暂停其他隔离中的线程。

GraalVM Enterprise版的另一个值得注意的新增功能是一个新的实验性的默认循环展开优化。循环展开是一种传统的编译器优化,可以提高计算繁重、以循环为中心的工作负载的性能。

部分循环展开是此优化的扩展形式,适用于循环迭代上限i未知的计数循环。转换创建循环的两个版本:可展开n次的循环的主版本导致优化的循环体进行地板(i/n)迭代,以及修复循环执行剩余的i%n次迭代。

部分展开的主要好处是减少了跳转的次数和循环控制值的更新,即较少的计数器增量和循环报头跳转。

您可以使用-Dgraal.EnterprisePartialUnroll=true启用新的优化。但是,请注意,这是实验性的,因此可能会导致未知错误。我们感谢所有反馈,因此如果您在实验过程中发现任何问题,请毫不犹豫地将其报告给GraalVM团队。

GraalVM Native Image仍然是一个非常令人兴奋的特性,在20.2.0中,它有几个重要的更新。我们在这里要重点介绍的两个功能是部署改进:

已经可以生成系统库(如libc)静态链接的本机可执行文件。此功能允许您创建完全独立的可执行文件,例如,可以在没有任何其他内容的最小从头开始的Docker容器中使用。

在20.2.0中,对Muslc进行了静态编译,现在您不必依赖第三方Muslc包。但它确实需要在生成本机可执行文件的系统中有一个可以工作的MUSL-GCC。

如果您还没有安装并准备好它,有一个关于如何获得它的说明。

然后,生成针对muslc静态链接的本机可执行文件只需向Native Image实用程序提供以下参数:

那么应用部署的Docker镜像可能如下所示,假设生成的可执行文件为`my-ative-app`:

它将创建一个空的Docker图像,并且只将您的应用程序放入其中。

将本机可执行文件部署到容器中的另一种有趣的方法是使用依赖性最小的小Docker映像,最好没有操作系统。例如,脑海中浮现的就是无病毒图像。

要构建本机可执行文件并静态链接除容器提供的libc之外的所有内容,请使用Native Image-H:+StaticExecutableWithDynamicLibC标志。

我们还改进了对GraalVM Enterprise中提供的基于G1的垃圾收集器的本机映像支持。如果您想尝试降低GC暂停时间的垃圾收集实现,请在构建时使用以下选项指定您的GC首选项:-H:+UseLowLatencyGC。本机可执行文件将正常构建,并且在运行时,您可以使用常用标志-XMX配置其内存使用情况,并使用-XX:+PrintGC或-XX:+VerboseGC监视GC活动。

最后,但并非最不重要的是,20.2.0中有一个潜在的突破性变化:类初始化策略已被更改,以包括更少的JDK库中要在构建时初始化的类。

如果您在构建时初始化应用程序类,它们可能会在构建时触发JDK库类的初始化,这将与新策略冲突,构建将不会成功。您可以通过自己为必要的类引入构建时类初始化来解决此问题。

例如,对于一个示例Micronaut应用程序,我需要在命令行中添加-initialize-at-build-time=com.sun.org.apache.xerces,com.sun.xml.Internal,jdk.xml.Internal,以便在构建时初始化这些类,就像在20.2.0版本之前一样。

如果您依赖框架或库来配置本机映像生成,则可能需要将其更新为可与20.2.0一起使用的更新版本。

对Truffle语言实现框架的一个重要更改是更改了语言解释器的默认内联启发式,其中内联预算基于Graal IR节点计数,而不是Truffle节点计数。这是一个非常有趣的变化,使得内联(这是一个非常重要的优化)在估计优化成本方面发挥了更好的作用。一个Truffle节点可以是任意复杂的,并通过“欺骗”内联启发式将其计为一个节点来超支内联预算。因此,根据Truffle节点计数估计内联的代码大小可能会导致低效的结果。

对于20.2.0中可用的语言实现API,一个非常受欢迎的新增功能是DynamicObject模型,以及利用它的库。您可以在文档中找到更多详细信息,但简而言之,它们允许语言实现更好地控制动态语言中的对象布局,并支持动态添加成员或更改类型。这允许按形状更好地处理对象,并使访问对象属性更有效率。

在GraalVM20.2.0中,我们将Node.js更新为版本12.18.0。我们还实现了许多建议:Intl.NumberFormat Unified API、逻辑赋值运算符、顶级等待建议,甚至Promise.Any建议(在ECMAScript 2021模式下可用)。

还有一个新实现的异步堆栈跟踪支持,您可以尝试一下。

我们想重点介绍GraalVM20.2.0中TruffleRuby的兼容性改进。除了您可以在发行说明中看到的大量其他更改之外,现在Ripper stdlib已经使用C扩展实现了。

此版本还改进了兼容性(特别是改进),并更新到Ruby 2.6.6,添加了更好的与其他语言的互操作性支持,并包括各种性能改进。

在GraalPython中最显著的变化中,我们实现了更好的本机扩展引用计数,以修复内存泄漏。

我们还向.pyc文件(.pyc文件永久存储从源.py文件编译的Python字节码)引入了代码序列化,这应该会改进Python程序的启动。

工具是GraalVM项目中非常重要的一部分。在20.2.0中,对VSCode中的GraalVM支持进行了许多改进。

语言服务器协议实施现在支持最新的协议版本3.15。GraalVMLSP是对VS代码中通常的LSP实现的一个非常有趣的补充-它可以注意到只有在您的程序运行时才能使用的动态信息,并使用这些动态信息为您在IDE中的内容助手中添加建议。

所有GraalVM VSCode扩展都被合并为一个,您可以从Marketplace获得。

VisualVM现在包含一个GoToSource操作,因此您可以从分析器跳到您首选的IDE。这是一个受欢迎的新增功能,可以快速导航到代码中最需要注意的位置。

然后右键单击其中一个视图中的类或方法名称,例如在CPU分析器中:

这些只是我们引以为豪的GraalVM20.2.0特性版本中的一些改进!请阅读发行说明中关于新的和值得注意的功能的更详细的概要,并考虑查看GitHub上的项目组件的ChangeLog!

下载GraalVM 20.2或GraalVM Enterprise 20.2,使用它来运行您的应用程序,并构建令人兴奋的新项目。如果您有任何反馈,请不要犹豫在Twitter、Slake或GitHub上让我们知道!