2019年11月25日
阪田 浩一 / ヤフー株式会社
GraalVM入門
自己紹介
2
• 阪田 浩一 (@jyukutyo)
• ヤフー株式会社 大阪拠点所属
• 第9代黒帯〜プログラミング言語(Java)〜
• JVMがとてつもなく好き
• 関西Javaエンジニアの会 代表&創設者
Oracle Code OneにおけるGraalVM
3
• セッション数が激増
• 2017: 4
• 2019: 37
• 内容はさまざま (機能については後述)
• GraalVMそのもの
• フレームワークでのネイティブイメージ活用
• Polyglot関連
GraalVMについての誤解
4
❌ Javaの
ネイティブイメージを
生成するためのツール
このセッションのゴール
5
GraalVMの概要を知り、
触ってみたくなること
GraalVMを一言で言うと
6
ユニバーサルVM
ここでのユニバーサルとは
7
あらゆる言語の
実行環境となれる
能力と機能が
あること
従来のJVMで実行できる言語
8
• Java
• JVM用に新たに作成したもの
• Scala, Kotlin, Groovyなど
• 他言語をJVM上に実装したもの
• JRubyなど
• など多数
現在GraalVMで実行できる言語
9
• JVMで実行できる言語すべて
• JavaScript
• Ruby
• Python
• R
GraalVMの構造
10
JVM (HotSpot VM)
+ α
+ α 機能の1つ
11
• Truffle: 言語実装用のライブラリ
• このライブラリを用いて実装した言語は、
すべてGraalVM上で実行できる
• トラフル (英)、トリュフ (仏)
Truffleで実装した言語
12
• GraalJS (JavaScript)
• ECMAScript 2019 仕様互換実装、Node.js v10.16.3
• TruffleRuby (Ruby, Experimental)
• Ruby 2.6.2 ベ ー ス
• GraalPython (Python , Experimental)
• Python3.7準拠
• FastR (R , Experimental)
• GNU R 3.5.1 互換実装
デモ
13
GraalVMで
JavaScriptを実行
セットアップ
14
https://www.graalvm.org/
GraalVMの2つのエディション
15
• Community Edition (CE)
• OSS (クラスパス例外付き GPL v2)
• Enterprise Edition (EE)
• ライセンス契約が必要 (評価は無償)
• CEよりパフォーマンスがよい
• CEよりネイティブコードのセキュリティ
を強化している
Oracle Labsが
開発
16
GraalVM EEも
Always Freeの
対象です
17
以降は
CEを前提にします
18
デモ
19
GraalVMで
JavaScriptを実行
(なお、Java 11で
Nashornは非推奨に
なりました)
20
単に各言語を
実行できるだけでは
ない
21
パフォーマンスを大幅に
低下させることなく、
言語間で
相互呼び出しができる
22
デモ
23
JavaScriptから
Javaを呼び出す
GraalVMのビジョン
24
パフォーマンスを
犠牲にせず、
言語間の抽象化をする
GraalVMとは
25
さまざまな言語を
実行できる (polyglot)、
ユニバーサルVM
開発ツールの
サポートもある
26
Google Chrome DevToolsでのデバッグ
27
Graal VisualVM
28
デモ
29
Chrome DevTools
でのデバッグ
あの処理、
別の言語のライブラリを
使うとすぐできるのに…
30
GraalVMとHotSpot VMの違い
31
HotSpot VM
Compiler Interface
C2C1
HotSpot VM
C++
GraalVM
Compiler
Interface
GraalVM
JITコンパイラC1
HotSpot VM
JVMCI
Java
GraalVM JITコンパイラ
32
• JVMCI (JVM Compiler Interface) を用いて
作成した新JITコンパイラ
• 以前は単にGraalと言われていた
• Javaで書かれている
ベンチマーク
33
現時点のベンチマーク結果は、右下の
URLからご確認ください
https://renaissance.dev/
アロケーションの多い
アプリケーションには、
GraalVM JITコンパイラが
有効
34
たとえば
リアクティブストリーム
で構築したものや
35
Scalaなど
関数型プログラミング
モデルで構築したもの
36
Twitter社の事例
37
• OpenJDKベースの独自JDKに、GraalVM JITコ
ンパイラをバックポート
• 2年前2017年には、すでに本番環境で活用
• 数千台のサーバ、Scalaアプリケーション
• サーバリソースを削減し、台数削減
• 大きなコスト削減になった
GraalVM JITコンパイラ
38
• Truffleで実装した言語は、
GraalVM JITコンパイラでの動作を
前提とする
GraalVMで動作する言語
39
HotSpot VM
JVMCI
GraalVM JITコンパイラ
JVM⾔語 Truffle
LLVMJS R Python
C C++
Fortran
Ruby
Java, Kotlin,
Scala,
JRubyなど
言語実装のしくみ
40
対象言語のASTの
インタプリタを
Truffle APIを用いて
Javaで実装する
対象コードのASTと
インタプリタの両方を
評価することで
高性能のコードを
生成できる
41
ゴールドマン・サックス社の事例
42
• 1990年代初め、独自に言語を開発
• 現在までコードが増え続ける
• 言語自体の運用開発が課題に
ゴールドマン・サックス社の事例
43
• その言語をTruffleベースに移行
• 他言語との相互呼び出しが可能に
• 言語実装のメンテナンス性が向上した
• 実行パフォーマンスが向上した
• 事例発表動画
• Oracle Code One 2018:
https://www.youtube.com/watch?v=MUECwHdr07Q
究極的には
44
自分で実装した
プログラミング言語を
GraalVMで実行できる
私もやってみました
45
https://github.com/jyukutyo/JVM-Math-Language
言語実装サンプル
46
• GraalVMのリポジトリ内
• SimpleLanguage
• https://github.com/graalvm/simplelanguage
• Simpleとあるけれど、簡単ではない
ここまでの内容
47
• GraalVM
• GraalVM JITコンパイラ
• Truffle: 言語実装用ライブラリ
• パフォーマンスを犠牲にせず
言語間の抽象化をする
ここまで
ネイティブイメージの
話題なし
48
GraalVMのネイティブイメージ生成
49
• ネイティブイメージ
(実行可能なバイナリ) を生成する機能
• 生成したイメージ (ファイル) をそのまま
実行する
• つまり、起動にJVM (JDK/JRE) が不要
この機能と、
今までの機能に
何の関連が??
50
答えは、
Oracle Database
51
Oracle Database
52
• ユーザ定義関数をJavaで作成できる
しかし、
• GraalVMの機能を組み込めば、Javaは
もちろん、他言語も使える
• 機能の更新は、GraalVM側に任せられる
Oracle Databaseに
GraalVMを組み込む
53
Oracle Databaseへ組み込むには
54
• JVMが課題
• サイズが大きい
• 初期化処理が長い
• メモリ使用量が大きい
• そのままでは、データベースでの
利用はできない
GraalVM自体を
ネイティブイメージに
する!
55
ネイティブイメージにすると
56
• JVMが不要
• サイズが小さく済む
• 起動時間が短くなる
• メモリ使用量が少なくなる
• ただし、同じプラットフォームでしか
動作しない
Oracle Database MLE
57
• MLE: Multilingal Engine
• https://www.oracle.com/technetwork/database/multilingual-
engine/overview/index.html
• MySQLでもMLE Pluginを開発中
select
validator.isEmail('alice@example.com’)
from dual;
こうした経緯で開発した
ネイティブイメージ
生成機能が
GraalVMの機能の1つ
となった
58
デモ
59
ネイティブイメージ
生成
+ α 機能の1つ
60
• Substrate VM
• ネイティブイメージの生成ツール、実行VM
• 実行時、GCやスレッドのスケジューリング、
コードのキャッシュなどを実施
• 単にVMであって、JVMではない
ネイティブイメージ生成プロセス
61
アプリケーション
ライブラリ
JDK
Substrate VM
下記の繰り返し:
解析ポイント
↓
初期化処理実⾏
↓
ヒープのスナップショット⽣成
ELFファイル
コード
(textセクション)
イメージヒープ
(dataセクション)
生成時に
初期化処理を実行し、
起動時間を
短縮する
62
生成において、
混乱しやすい部分を
いくつか紹介します
63
生成時の初期化
64
import java.util.Date;
class InitializedDate {
static final Date INITIALIZED_DATE = new Date();
}
class InitializeSample {
public static void main(String[] args) {
System.out.println("INITIALIZED_DATE: " +
InitializedDate.INITIALIZED_DATE);
System.out.println("main: " + new Date());
}
} 2つの日付は、異なる??
初期化タイミング
65
• アプリケーションのクラスは、
すべて実行時に初期化
• それ以外のクラスは、生成時初期化
• --initialize-at-build-time=[クラス名]
• 生成時に初期化
• --initialize-at-run-time=[クラス名]
• 実行時に初期化
生成時初期化を指定すると…
66
import java.util.Date;
class InitializedDate {
static final Date INITIALIZED_DATE = new Date();
}
class InitializeSample {
public static void main(String[] args) {
System.out.println("INITIALIZED_DATE: " +
InitializedDate.INITIALIZED_DATE);
System.out.println("main: " + new Date());
}
}
$ ./initializesample
INITIALIZED_DATE: Wed Oct 23 15:05:19 JST 2019
main: Wed Oct 23 15:08:07 JST 2019
リフレクションやJNIのサポート
67
• 現在は利用可能に
1. 生成時の静的解析
• Class.getMethod(String, Class[]) など
2. 設定ファイルに明示的に記述
• 参考: Tracing Agent
リフレクション利用設定
68
[
{
"name" : "java.lang.String",
"fields" : [
{ "name" : "value", "allowWrite" : true }
],
"methods" : [
{ "name" : "format", "parameterTypes" :
["java.lang.String", "java.lang.Object[]"] }
]
}
]
ライブラリでの対応
69
• 設定ファイルを
META-INF/native-imageに配置
• 生成時に自動的に読み込まれる
ネイティブイメージの現状
70
• Experimental
• サポートプラットフォーム
• x86 64ビットシステム
• LinuxまたはmacOS
ネイティブイメージのメリットまとめ
71
• 起動時間が短くなる
• メモリ使用量が少なくなる
• サイズが小さくなる
どんなアプリケーション
でも、
ネイティブイメージに
する方がよいのか?
72
JITコンパイル (JVM)
と
AOTコンパイル
(GraalVM)
73
https://twitter.com/thomaswue/status/1145603781108928513
ネイティブイメージが適切なケース
75
• FaaS
• 起動してすぐに終了する
• クラウドで実行する
大規模アプリケーション
• リソースを節約し、コストを削減する
ネイティブイメージ対応フレームワーク
76
• Micronaut
• Quarkus
• Helidon
• Spring Framework, Bootも対応作業中
(現在はExperimental)
GraalVMのリリースロードマップ
77
• 3ヶ月ごと、年4回のリリース
• 2019/11 – GraalVM 19.3
• 2020/02 – 20.0
• 2020/05 – 20.1
• 2020/08 – 20.2
• 2020/11 – 20.3
11月の19.3にて、
Java 11対応予定!
(現状8のみ)
78
GraalVMのリリースロードマップ
79
• 年間最後のリリースは、LTS
• 2019/11 – 19.3
• 2020/11 – 20.3
• 次の1年間、アップデートを提供
• 19.3は、2020年末まで
• 20.3は、2021年末まで
• CEのケースであり、EEは別となる
OpenJDKとは別の、
独立した開発
80
GraalVMのパッチアップデート
81
• 1月、4月、7月、10月
• 2020/02 – 20.0
• 2020/04 – 20.0.1(CPU) <- LTS以外は1回のみ
...
• 2020/11 – 20.3
• 2021/01 – 20.3.1(CPU)
• 2021/04 – 20.3.2(CPU)
• 2021/07 – 20.3.3(CPU)
• 2021/10 – 20.3.4(CPU)
AOTでも
JITと同じくらいの
ピーク時パフォーマンス
が今後の目標、
とのこと
82
まとめ GraalVMとは
83
• GraalVM JITコンパイラ
• Truffle
• 言語実装用ライブラリ
• SubstrateVM
• ネイティブイメージ用ツール
GraalVMの2つのモード
84
• JITモード
• JVMとGraalVM JITコンパイラで
アプリケーションを実行
• AOTモード
• ネイティブイメージを生成し、JVMなしで
アプリケーションを実行
• どちらのモードのことなのか、意識する
GraalVMのサンプル事例
85
• GraalVM JITコンパイラ単体で、
ピーク時のパフォーマンスを向上させる
• Truffleで、複数言語を活用した
アプリケーションを構築
• SubstrateVMで、ネイティブイメージを
生成し、起動時間短縮とリソース消費削減

Guide to GraalVM (Oracle Groundbreakers APAC 2019 Tour in Tokyo)