下一代JVM:GraalVM的十大特性

GraalVM有许多不同的组件,如果你只是听说过它或有些简单的了解,肯定无法一窥全豹。本文将列举下GraalVM的几大常用功能,看看它们都能做些什么。

高性能的现代Java
占用资源少,启动速度快
JavaScript, Java, Ruby以及R混合编程
在JVM上运行原生语言
跨语言工具
JVM应用扩展
原生应用扩展
本地Java库
数据库支持多语言
创建自己的语言
本文将要介绍的内容在GraalVM 19.0.0(可以从https://www.graalvm.org/downloads上下载到)上验证通过。这里我用的是MacOS平台的企业版,可以免费使用,里面的命令也可用于Linux平台。下面介绍的大部分功能在社区版上也是支持的。

环境配置
先从graalvm.org/downloads下载GraalVM 19.0.0,然后将它添加到$PATH中。默认情况下GraalVM可以支持Java和JavaScript。

$ git clone https://github.com/chrisseaton/graalvm-ten-things.git
$ cd foo
$ tar -zxf graalvm-ee-darwin-amd64-19.0.0.tar.gz.tar.gz
# or graalvm-ee-darwin-linux-19.0.0.tar.gz on Linux
$ export PATH=graalvm-ee-19.0.0/Contents/Home/bin:KaTeX parse error: Expected 'EOF', got '#' at position 10: PATH #̲ or PATH=graalv…PATH on Linux
GraalVM自带了JavaScript的实现,它还有一个包管理工具gu,你可以用它来安装其它语言。我安装了Ruby, Python和R语言,以及native-image工具。这些都可以从github中下载到。

$ gu install native-image
$ gu install ruby
$ gu install python
$ gu install R
现在运行下java或js便能看到它们的运行时的GraalVM版本号。

$ java -version
java version “1.8.0_212”
Java™ SE Runtime Environment (build 1.8.0_212-b31)
Java HotSpot™ GraalVM EE 19.0.0 (build 25.212-b31-jvmci-19-b01, mixed mode)

$ js --version
GraalVM JavaScript (GraalVM EE Native 19.0.0)
1.高性能的现代Java
GraalVM中的Graal得名于它的Graal编译器。GraalVM是根据One VM to Rule Them All这篇论文的思想实现的,也就说它只实现了一套编译器库,却能用于不同的场合。比如说我们可以用GraalVM的编译器来进行ahead-of-time或just-in-time(JIT)编译,编译不同的语言,编译到不同的平台上。

最简单的使用方式就是把它当作Java的JIT编译器来使用。

我们用下面这段程序作一个例子,它会输出文档中使用频率前十的单词。里面用到了Java的新特性,包括Stream和Collector。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TopTen {

public static void main(String[] args) {
    Arrays.stream(args)
            .flatMap(TopTen::fileLines)
            .flatMap(line -> Arrays.stream(line.split("\\b")))
            .map(word -> word.replaceAll("[^a-zA-Z]", ""))
            .filter(word -> word.length() > 0)
            .map(word -> word.toLowerCase())
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
            .entrySet().stream()
            .sorted((a, b) -> -a.getValue().compareTo(b.getValue()))
            .limit(10)
            .forEach(e -> System.out.format("%s = %d%n", e.getKey(), e.getValue()));
}

private static Stream<String> fileLines(String path) {
    try {
        return Files.lines(Paths.get(path));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

}
可以使用GraalVM自带的javac编译器,不过对这个示例来说无所谓,用系统中原有的javac来编译也是可以的。

$ javac TopTen.java

如果使用GraalVM中的java来运行这个程序的话,就会自动用上Graal的JIT编译器了——不再需要额外的配置。这里我们使用time来计算程序从运行到结束的真实消耗的系统时间,并没有使用更复杂的微基准测试工具,因为这里的输入数据非常大,也没必要纠结这几秒的时间。large.txt文件的大小是150MB。

$ make large.txt
$ time java TopTen large.txt
sed = 502701
ut = 392657
in = 377651
et = 352641
id = 317627
eu = 317627
eget = 302621
vel = 300120
a = 287615
sit = 282613

real 0m12.950s
user 0m17.827s
sys 0m0.622s
GraalVM是用Java编写的,不像其它的JIT编译器那样都是用C++写的。这样相对于传统的编译器来说,更容易对它进行优化,比如像HotSpot中不支持的偏向逃逸分析(partial escape analysis)等新的优化技术都可以很容易在它上面实现。这些技术可以让Java程序运行速度得到显著的提升。

如果想和不启用GraalVM JIT编译器的结果做下对比,可以使用-XX:-UseJVMCICompiler来关掉它。JVMCI是GraalVM与JVM间的接口。可以和标准的JVM的做一下性能对比。

$ time java -XX:-UseJVMCICompiler TopTen large.txt
sed = 502701
ut = 392657
in = 377651
et = 352641
id = 317627
eu = 317627
eget = 302621
vel = 300120
a = 287615
sit = 282613

real 0m19.602s
user 0m20.357s
sys 0m0.498s
结果表明这个Java程序在GraalVM中的运行时间只有传统JVM的2/3。在虚拟机这个领域,哪怕是个位数的性能提升都是很大的进步,所以这个结果真的算是挺了不起了。

即便用社区版来进行测试,结果也要比HotSpot要好,但和企业版相比还是逊色了点。

Twitter是唯一一个已经在生产环境中使用GraalVM的公司,他们声称GraalVM为公司节约了大量的成本。Twitter用它来运行scala程序——GraalVM是基于JVM字节码来工作的,因此JVM上的语言它都能支持。

这是GraalVM的第一个用途,它为我们带来了一个更加强劲的JIT编译器。

2.资源占用低,启动速度快
在长时间运行,对性能要求较高的领域,Java平台是比较有优势的,但对于那些只需要短暂运行的应用而言,启动时间过长和占用资源过高都是一个问题。

比如说,仍旧是前面这个程序,不过输入文件的大小从150MB变成了1kB,对于一个这么小的文件而言,消耗的时间相对来说就很长了,并且还需要使用接近70MB的内存。我们加上-l参数来同时打印出所消耗内存及时间。

$ make small.txt
$ /usr/bin/time -l java TopTen small.txt
# -v on Linux instead of -l
sed = 6
sit = 6
amet = 6
mauris = 3
volutpat = 3
vitae = 3
dolor = 3
libero = 3
tempor = 2
suscipit = 2
0.17 real 0.28 user 0.04 sys
70737920 maximum resident set size

GraalVM有一个工具能解决这个问题。前面说过GraalVM其实更像一个编译器库,有很多不同的用法。其

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值