在JDK11上GraalVM的JavaScript性能是Nashorn的两倍


GraalVM是一个运行时平台,它支持Java和其他基于Java字节码的语言,但也支持其他语言,如JavaScript,Ruby,Python或LLVM。我们坚信,正如我们目前所知,它是语言虚拟机的未来。
但是,我们知道从已建立的Oracle JVM或OpenJDK切换到GraalVM是一个大胆的步骤,您可能不想完全采用它。但是,您可能希望在库存JVM上尝试GraalVM项目的一些很酷的功能。
​​​​​​在这篇博客文章中,我们将展示如何从示例Maven应用程序中使用GraalVM的JavaScript引擎。我们还展示了如何在OpenJDK 11库存中使用GraalVM的JavaScript引擎,包括Graal作为JIT(即时)编译器以获得更好的峰值性能。这样,GraalVM的JavaScript引擎可以用作已弃用的Nashorn JavaScript引擎的替代品。我们将在Maven应用程序上进行演示,因为Maven central上提供了所有必需的工件。

GraalVM的JavaScript和Graal编译器
可能出现的一个问题是:GraalVM的JavaScript引擎与Graal的关系是什么; 我可以只使用JavaScript引擎并省略Graal吗?
如果你这样做,事情就会完全奏效。然后,您可以解析并执行任何(有效的)JavaScript代码。GraalVM的JavaScript引擎是一个适用于任何Java 8+实现的Java应用程序。JavaScript执行是围绕抽象语法树(AST)解释器构建的,可以像任何其他Java应用程序一样执行。每个Java虚拟机都会在一定程度上对其进行优化,但JavaScript执行仍将被解释,因此速度很慢。
但是,Graal编译器有一些特殊的技巧可以将这个AST解释器转换为高度优化的机器代码。它将适应所执行的JavaScript应用程序,并将应用程序和解释器编译为机器代码,从而在运行时将其有效地转换为JavaScript编译器。在短暂的预热阶段之后,如果在启用了Graal编译器的JVM上执行GraalVM的JavaScript引擎,则JavaScript应用程序将实现接近本机的性能。

示例应用

我们准备了一个展示相关设置的示例应用程序。这个基于Maven的示例可以作为一个起点,使您能够将基于Nashorn的JavaScript应用程序传输到GraalVM的带有Graal支持的JavaScript。
该示例以JavaScript中的Prime数计算为中心,在Java代码中消费调用它。它展示了如何使用首选org.graalvm.polyglot接口访问GraalVM的JavaScript ,还使用javax.script(JSR 223 ScriptEngine)接口。此外,示例代码通过Nashorn引擎上的ScriptEngine执行(如果可用)。执行相同数量的预热和测量迭代并作为简单基准打印,显示相应引擎上所需的执行时间(较低的值更好)。
这个例子可以在GitHub上找到:
https://github.com/graalvm/graal-js-jdk11-maven-demo

请注意,代码的特殊优点不是讨论的有趣部分,通常可以将Java和JavaScript源分成单独的文件等等。此示例主要关注用于执行多语言Java和JavaScript代码的基础结构。如果使用以下命令编译并执行它,应用程序应该是开箱即用的; 确保您使用JDK11 JAVA_HOME指向它。

export JAVA_HOME = / path / to / JDK11 
mvn clean && mvn package && mvn exec:exec @ graal

这将确保您使用Graal进行GraalVM JavaScript代码的JIT编译。在这个应用程序中,当我们测量时,GraalVM的JavaScript大约是Nashorn的两倍(请试试你的机器,YMMV)。

为了便于比较,您可以在不启用Graal编译的情况下执行相同的基准测试:

mvn clean && mvn package && mvn exec:exec @nograal

在该模式下,在没有Graal作为JIT编译器的情况下执行,GraalVM / JavaScript的性能显着下降。

一些技术见解
现场背后发生了什么?在pom.xml文件中声明了相关包的几个依赖项,包括org.graalvm.compiler和org.graalvm.js。这些可以在Maven中心获得,并从那里下载。

将三个参数传递给JVM,如插件配置部分中所声明的,它在JVM上启用Graal编译:

-XX:+UnlockExperimentalVMOptions
此标志启用以下选项
-XX:+EnableJVMCI
通过JVMCI(Java虚拟机编译器接口)实现Java代码的编译
--upgrade-module-path
在模块路径上放置正确版本的Graal,以便它可以用作GraalVM / JavaScript的编译器

结论
在这篇文章中,我们研究了如何从Maven Central中使用GraalVM的JavaScript引擎工件并在库存JDK上运行它。如果不能访问Graal编译器,则此设置中的JavaScript代码性能可能不是最佳的 - 幸运的是,您可以使用一堆命令行选项启用Graal编译器,并获得更快的JavaScript执行速度。在Graal编译器的存在下,GraalVM的JavaScript明显快于Nashorn。

怎么在OpenJDK 11库存中构建GraalVM的JavaScript引擎