Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
© 2020 NTT DATA Corporation
Javaコードが速く実⾏される秘密
- JITコンパイラ⼊⾨
2020年11⽉7⽇ JJUG CCC 2020 Fall
株式会社NTTデータ 技術開発本部
阪⽥ 浩⼀
© 2020 NTT DATA Corporation 2
⾃⼰紹介
• 阪⽥ 浩⼀(さかた -)
• 通称 じゅくちょー
• JVMになりたい⼈
• NTTデータでJava/OpenJDK + GraalVMの
研究開発とそのサポート業に従事...
© 2020 NTT DATA Corporation 3
このセッションの役割
JVMの現在の
実⾏速度を実現した
JITコンパイラの仕組みを
(概観として)伝える
© 2020 NTT DATA Corporation 4
Javaアプリケーションの
実⾏までの流れを
おさらいしましょう
© 2020 NTT DATA Corporation 5
javacでのコンパイル
Javaコード
コンパイル(javac)
クラスファイル
© 2020 NTT DATA Corporation 6
cafe babe 0000 0034 001d 0a00 0600 0f09 .......4........
0010 0011 0800 120a 0013 0014 0700 ...
© 2020 NTT DATA Corporation 7
メソッドの処理を
Javaバイトコードで
記述する
© 2020 NTT DATA Corporation 8https://docs.oracle.com/javase/specs/jvms/se13/html/jvms-7.html
© 2020 NTT DATA Corporation 9
Javaでのコンパイル(javac)
実施タイミング アプリケーション実⾏前
⼊⼒ Javaコード
出⼒ Javaバイトコード
© 2020 NTT DATA Corporation 10
$ javap -c HelloWorld
class HelloWorld {
...
public static void main(java.lang.String...);
...
© 2020 NTT DATA Corporation 11
JVMは
クラスファイルを
読み込み、
アプリケーションを
実⾏する
© 2020 NTT DATA Corporation 12
JVMは
処理をどのように
実⾏する︖
© 2020 NTT DATA Corporation 13
バイトコードを
インタプリト、
つまり逐次処理する
© 2020 NTT DATA Corporation 14
今から25年前…
Javaの実⾏は
遅かった
© 2020 NTT DATA Corporation 15
理由の1つは、
すべての処理が
インタプリタ実⾏
だったこと
© 2020 NTT DATA Corporation 16
Java (J2SE) 1.3で
JITコンパイルを
標準で使うように
© 2020 NTT DATA Corporation 17
このJITコンパイルが
今でもJavaの速さの
主な要因
© 2020 NTT DATA Corporation 18
JITコンパイルの仕組み
Javaバイトコード
JITコンパイル
機械語
プロファイル情報
© 2020 NTT DATA Corporation 19
JITコンパイル
「実⾏中」に
機械語へコンパイル︕
JVM
© 2020 NTT DATA Corporation 20
各プラットフォーム
(主にCPU)
の機械語を
⽣成、キャッシュして
実⾏する
© 2020 NTT DATA Corporation 21
さらに、
実⾏時の情報を
プロファイリングし、
それを機械語⽣成に
活⽤する
© 2020 NTT DATA Corporation 22
その結果、
実⾏パフォーマンスが
向上する
© 2020 NTT DATA Corporation 23
コードをすべて
JITコンパイルしているのか︖
© 2020 NTT DATA Corporation 24
前提
JITコンパイルは
アプリケーションの実⾏中に
動作するものである
© 2020 NTT DATA Corporation 25
トレードオフ
JITコンパイル処理⾃体が
リソースを消費する
© 2020 NTT DATA Corporation 26
トレードオフのバランスを取る
プロファイル情報から
よく実⾏する処理
(頻繁に呼ばれる
メソッドなど)
をコンパイル対象にする
© 2020 NTT DATA Corporation 27
よく実⾏する処理
=
ホットスポット
© 2020 NTT DATA Corporation 28
(おそらく今使っている) JVM
HotSpot VM
(OpenJDK / Oracle JDK)
© 2020 NTT DATA Corporation 29
さらなるトレードオフ
よりよい機械語を
⽣成するには、
より⻑いコンパイル時間が
必要となる
© 2020 NTT DATA Corporation 30
さらなるトレードオフ
コンパイル時間短縮
or
速いコードの⽣成
© 2020 NTT DATA Corporation 31
HotSpot VMでは
2つのJITコンパイラを
使う
© 2020 NTT DATA Corporation 32
HotSpot VMでの2つのJITコンパイラ
• C1コンパイラ
• コンパイル時間が短い
• それほど速くない機械語する
• C2コンパイラ
• 速いコードを⽣成する
• コンパ...
© 2020 NTT DATA Corporation 33
メソッドに対するコンパイルと呼び出し時間のイメージ
C2
C1
コンパイル時間が⻑くても、
その後の処理実⾏が⾼速になり、
「元が取れる」
© 2020 NTT DATA Corporation 34
Java歴が⻑い⼈向け
昔、実⾏オプションで
-server って
つけてましたよね︖
© 2020 NTT DATA Corporation 35
HotSpot VMでの2つのJITコンパイラ
• C1コンパイラ(clientコンパイラ)
• コンパイル時間が短い
• それほど速くない機械語する
• C2コンパイラ(serve...
© 2020 NTT DATA Corporation 36
-server とは、
C2コンパイラを
使⽤する、
という意味です
© 2020 NTT DATA Corporation 37
Java 8からは-server不要
Tiered Compilation
(階層型コンパイル)
がデフォルトに
なったため
© 2020 NTT DATA Corporation 38
バイトコード C1⽣成機械語 C2⽣成機械語
Tiered Compilation概要
• C1とC2の両⽅を使う
© 2020 NTT DATA Corporation 39
JITコンパイルのログを
出⼒してみよう︕
© 2020 NTT DATA Corporation 40
JITコンパイルのログ設定
• 以下のオプションを付ける
• -XX:+PrintCompilation
• コンソールにコンパイルログを出⼒する
© 2020 NTT DATA Corporation 41
PrintCompilationの出⼒
181 416 4 java.lang.AbstractStringBuilder::append (45 bytes)
182 417 ! ...
© 2020 NTT DATA Corporation 42
デモ
SpringBoot起動での
JITコンパイルログ出⼒
© 2020 NTT DATA Corporation 43
実際のJITコンパイルログ
32 5 3 java.lang.String::coder (15 bytes)
...
150 235 4 java.lang.String::cod...
© 2020 NTT DATA Corporation 44
JITコンパイルの最適化レベル
最適化レベル: 0
インタプリタ
⼀般的ケース
プロファイリング
なし
ベーシック
カウンタのみ
詳細
3 4
C2が詰まっているケース 0 2 43...
© 2020 NTT DATA Corporation 45
JITコンパイラの最適化レベル
0 インタプリタ実⾏
1 C1 (プロファイリングなし)
2
C1 (ベーシックカウンタのみ
プロファイリング)
3 C1 (完全なプロファイリング)...
© 2020 NTT DATA Corporation 46
$ javap -c --module java.base java.lang.String
...
byte coder();
Code:
0: getstatic
3: ifeq...
© 2020 NTT DATA Corporation 47
再掲︓実際のJITコンパイルログ
32 5 3 java.lang.String::coder (15 bytes)
...
150 235 4 java.lang.String::...
© 2020 NTT DATA Corporation 48
JITコンパイルのログ設定
• 以下のオプションを付ける
• -XX:+PrintCompilation
• コンソールにコンパイルログを出⼒する
• Unified JVM Log...
© 2020 NTT DATA Corporation 49
JITコンパイラが
コンパイルしたメソッドは
わかったけど
⽣成した機械語も⾒たい︕
© 2020 NTT DATA Corporation 50
たとえばこういったケース
• あるメソッドがJITコンパイルされているか
確認したい
• パフォーマンスに⼤きく影響するメソッドである場合
• 実⾏中のどの時点でJITコンパイルされ...
© 2020 NTT DATA Corporation 51
HSDIS(HotSpot Disassembler)
• JIT⽣成の機械語をアセンブリに変換して
出⼒するライブラリ
• HotSpot VM⽤(通常のOpenJDKとOracl...
© 2020 NTT DATA Corporation 52
HSDISの出⼒
Demo2.workload(I)I (Demo2.workload(int)) [0x000000010b997b20, 0x000000010b997b60] ...
© 2020 NTT DATA Corporation 53
デモ
SpringBoot起動時の
アセンブリ表⽰
© 2020 NTT DATA Corporation 54
読みやすいとは
⾔えません
© 2020 NTT DATA Corporation 55
出⼒するメソッドを指定できる
• CompileOnlyオプションを付与する
• -XX:CompileOnly=String::startsWith -XX:CompileComm...
© 2020 NTT DATA Corporation 56
参考︓JITWatch
• JITコンパイルログの解析と可視化ができる
• https://github.com/AdoptOpenJDK/jitwatch
© 2020 NTT DATA Corporation 57
Javaバイトコードを
機械語にする
プロセスは︖
© 2020 NTT DATA Corporation 58
JITコンパイルのプロセス
Java
バイトコード
IR
(中間表現)
機械語
最適化を適⽤し、
IRを変更するサイクル
を繰り返す
① ③
②
© 2020 NTT DATA Corporation 59
IR(Intermediate Representation)
• コードをデータ構造で表現する
• JVMでは、グラフで表現している
• プログラムの依存をグラフにする
• 通称 ...
© 2020 NTT DATA Corporation 60
例: x + y をグラフにする
© 2020 NTT DATA Corporation 61
例: getX() + getY() をグラフにする
© 2020 NTT DATA Corporation 62
例: メソッドの呼び出し順序を考慮
⻩⾊が実⾏順序、緑⾊がデータフロー
© 2020 NTT DATA Corporation 63
JVMのIRグラフを
⾒てみよう
(ただし、C2ではなく
GraalVM JITコンパイラ)
© 2020 NTT DATA Corporation 64
IdealGraphVisualizer
IRグラフ可視化ツール
• ただし、GraalVM JITコンパイラ⽤
• -Dgraal.Dump=:1 オプションをつけて実⾏する
• ...
© 2020 NTT DATA Corporation 65
参考: C2とGraalVM JITコンパイラ
• C2
• OpenJDKのデフォルト
• C++で書かれている
• GraalVM JITコンパイラ
• GraalVMのデフォル...
© 2020 NTT DATA Corporation 66
デモ
IRグラフをダンプして
IGVで表⽰する
© 2020 NTT DATA Corporation 67
JITコンパイルでの
最適化とは、
このグラフに対する
パターンマッチとなる
イメージ
© 2020 NTT DATA Corporation 68
ものすごくラフな例
Aノード Bノード
Cノード
Dノード Dノード
Eノード
最適化パターンにマッチ︕
© 2020 NTT DATA Corporation 69
JITコンパイラの構成
バイト
コード
フロント
エンド
バック
エンド
機械語
© 2020 NTT DATA Corporation 70
フロントエンド
• ハードウェアから独⽴
• バイトコードからIRを⽣成する
• IRに最適化をほどこす
• IRは、HIRと呼ぶ
• High-Level IR: ⾼⽔準中間表現
© 2020 NTT DATA Corporation 71
バックエンド
• ハードウェアに依存
• レジスタを割り当てる
• IRから機械語を⽣成する
• IRはLIRと呼ぶ
• Low-Level IR: 低⽔準中間⾔語
© 2020 NTT DATA Corporation 72
JITコンパイルの処理の流れ
クラス
ロード
バイト
コード
HIR
HIR LIR
LIR
機械語
コード
フロントエンド バックエンド
HIR⽣成
最適化 レジスタ割当
コード⽣成
© 2020 NTT DATA Corporation 73
o.g.compiler.core.GraalCompiler
public static <T extends CompilationResult> T
compile(Reque...
© 2020 NTT DATA Corporation 74
最適化
• メソッドのインライン化
• ループアンロール
• デッドコード削除
• ロック粗粒化 / ロック省略
• エスケープ解析 (厳密には最適化ではない)
• などなど多数
© 2020 NTT DATA Corporation 75
ホットパスでのコンパイル
ノード ノード
ノード
ノード
プロファイル結果から、
左ルートを前提とした
コードを⽣成する
© 2020 NTT DATA Corporation 76
実⾏が右ルートに⾏く場合は︖
ノード ノード
ノード
ノード
⽣成したコードにある
トラップに⼊る
© 2020 NTT DATA Corporation 77
脱最適化: Deoptimization
• JITコンパイラが⽴てた前提から
外れた実⾏となった場合
• if – else if でまれな経路に⼊る
• クラスロードでインタフェ...
© 2020 NTT DATA Corporation 78
JITコンパイルのライフサイクル
インタプリタ
コードキャッシュ
C1
C2
脱最適化
© 2020 NTT DATA Corporation 79
コードキャッシュ
• 機械語コードは
CodeCache (C++オブジェクト)内に
配置する
• -XX:ReservedCodeCacheSize でキャッシュサイズを指定
• ...
© 2020 NTT DATA Corporation 80
Java HotSpot(TM) 64-Bit Server VM warning: CodeCache is full.
Compiler has been disabled.
J...
© 2020 NTT DATA Corporation 81
アプリケーションの
パフォーマンスが
低下する
© 2020 NTT DATA Corporation 82
今回扱っていない話題
• コンパイルキュー
• OSR: On Stack Replacement
• 各最適化⼿法の詳細
• SSA: Static Single Assignme...
© 2020 NTT DATA Corporation 83
まとめ
• JITコンパイラ
• バイトコードを機械語に変換する
• HotSpot VMのJITコンパイラ
• C1とC2でTiered Compilation
• HSDIS(+...
© 2020 NTT DATA Corporation本資料に記載されている会社名、商品名、⼜はサービス名は、各社の登録商標⼜は商標です
Prochain SlideShare
Chargement dans…5
×

Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)

Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨
(2020年11⽉7⽇ JJUG CCC 2020 Fall 講演資料)

NTTデータ 技術開発本部
先進コンピューティング技術センタ
阪⽥ 浩⼀

  • Soyez le premier à commenter

Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)

  1. 1. © 2020 NTT DATA Corporation Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨ 2020年11⽉7⽇ JJUG CCC 2020 Fall 株式会社NTTデータ 技術開発本部 阪⽥ 浩⼀
  2. 2. © 2020 NTT DATA Corporation 2 ⾃⼰紹介 • 阪⽥ 浩⼀(さかた -) • 通称 じゅくちょー • JVMになりたい⼈ • NTTデータでJava/OpenJDK + GraalVMの 研究開発とそのサポート業に従事しています • Javaチャンピオン • OpenJDK Author jyukutyo
  3. 3. © 2020 NTT DATA Corporation 3 このセッションの役割 JVMの現在の 実⾏速度を実現した JITコンパイラの仕組みを (概観として)伝える
  4. 4. © 2020 NTT DATA Corporation 4 Javaアプリケーションの 実⾏までの流れを おさらいしましょう
  5. 5. © 2020 NTT DATA Corporation 5 javacでのコンパイル Javaコード コンパイル(javac) クラスファイル
  6. 6. © 2020 NTT DATA Corporation 6 cafe babe 0000 0034 001d 0a00 0600 0f09 .......4........ 0010 0011 0800 120a 0013 0014 0700 1507 ................ 0016 0100 063c 696e 6974 3e01 0003 2829 .....<init>...() 5601 0004 436f 6465 0100 0f4c 696e 654e V...Code...LineN 756d 6265 7254 6162 6c65 0100 046d 6169 umberTable...mai 6e01 0016 285b 4c6a 6176 612f 6c61 6e67 n...([Ljava/lang 2f53 7472 696e 673b 2956 0100 0a53 6f75 /String;)V...Sou 7263 6546 696c 6501 000f 4865 6c6c 6f57 rceFile...HelloW 6f72 6c64 2e6a 6176 610c 0007 0008 0700 orld.java....... クラスファイル
  7. 7. © 2020 NTT DATA Corporation 7 メソッドの処理を Javaバイトコードで 記述する
  8. 8. © 2020 NTT DATA Corporation 8https://docs.oracle.com/javase/specs/jvms/se13/html/jvms-7.html
  9. 9. © 2020 NTT DATA Corporation 9 Javaでのコンパイル(javac) 実施タイミング アプリケーション実⾏前 ⼊⼒ Javaコード 出⼒ Javaバイトコード
  10. 10. © 2020 NTT DATA Corporation 10 $ javap -c HelloWorld class HelloWorld { ... public static void main(java.lang.String...); Code: 0: getstatic #2 3: ldc #3 5: invokevirtual #4 8: return } javap
  11. 11. © 2020 NTT DATA Corporation 11 JVMは クラスファイルを 読み込み、 アプリケーションを 実⾏する
  12. 12. © 2020 NTT DATA Corporation 12 JVMは 処理をどのように 実⾏する︖
  13. 13. © 2020 NTT DATA Corporation 13 バイトコードを インタプリト、 つまり逐次処理する
  14. 14. © 2020 NTT DATA Corporation 14 今から25年前… Javaの実⾏は 遅かった
  15. 15. © 2020 NTT DATA Corporation 15 理由の1つは、 すべての処理が インタプリタ実⾏ だったこと
  16. 16. © 2020 NTT DATA Corporation 16 Java (J2SE) 1.3で JITコンパイルを 標準で使うように
  17. 17. © 2020 NTT DATA Corporation 17 このJITコンパイルが 今でもJavaの速さの 主な要因
  18. 18. © 2020 NTT DATA Corporation 18 JITコンパイルの仕組み Javaバイトコード JITコンパイル 機械語 プロファイル情報
  19. 19. © 2020 NTT DATA Corporation 19 JITコンパイル 「実⾏中」に 機械語へコンパイル︕ JVM
  20. 20. © 2020 NTT DATA Corporation 20 各プラットフォーム (主にCPU) の機械語を ⽣成、キャッシュして 実⾏する
  21. 21. © 2020 NTT DATA Corporation 21 さらに、 実⾏時の情報を プロファイリングし、 それを機械語⽣成に 活⽤する
  22. 22. © 2020 NTT DATA Corporation 22 その結果、 実⾏パフォーマンスが 向上する
  23. 23. © 2020 NTT DATA Corporation 23 コードをすべて JITコンパイルしているのか︖
  24. 24. © 2020 NTT DATA Corporation 24 前提 JITコンパイルは アプリケーションの実⾏中に 動作するものである
  25. 25. © 2020 NTT DATA Corporation 25 トレードオフ JITコンパイル処理⾃体が リソースを消費する
  26. 26. © 2020 NTT DATA Corporation 26 トレードオフのバランスを取る プロファイル情報から よく実⾏する処理 (頻繁に呼ばれる メソッドなど) をコンパイル対象にする
  27. 27. © 2020 NTT DATA Corporation 27 よく実⾏する処理 = ホットスポット
  28. 28. © 2020 NTT DATA Corporation 28 (おそらく今使っている) JVM HotSpot VM (OpenJDK / Oracle JDK)
  29. 29. © 2020 NTT DATA Corporation 29 さらなるトレードオフ よりよい機械語を ⽣成するには、 より⻑いコンパイル時間が 必要となる
  30. 30. © 2020 NTT DATA Corporation 30 さらなるトレードオフ コンパイル時間短縮 or 速いコードの⽣成
  31. 31. © 2020 NTT DATA Corporation 31 HotSpot VMでは 2つのJITコンパイラを 使う
  32. 32. © 2020 NTT DATA Corporation 32 HotSpot VMでの2つのJITコンパイラ • C1コンパイラ • コンパイル時間が短い • それほど速くない機械語する • C2コンパイラ • 速いコードを⽣成する • コンパイル時間が⻑くなる
  33. 33. © 2020 NTT DATA Corporation 33 メソッドに対するコンパイルと呼び出し時間のイメージ C2 C1 コンパイル時間が⻑くても、 その後の処理実⾏が⾼速になり、 「元が取れる」
  34. 34. © 2020 NTT DATA Corporation 34 Java歴が⻑い⼈向け 昔、実⾏オプションで -server って つけてましたよね︖
  35. 35. © 2020 NTT DATA Corporation 35 HotSpot VMでの2つのJITコンパイラ • C1コンパイラ(clientコンパイラ) • コンパイル時間が短い • それほど速くない機械語する • C2コンパイラ(serverコンパイラ) • 速いコードを⽣成する • コンパイル時間が⻑くなる
  36. 36. © 2020 NTT DATA Corporation 36 -server とは、 C2コンパイラを 使⽤する、 という意味です
  37. 37. © 2020 NTT DATA Corporation 37 Java 8からは-server不要 Tiered Compilation (階層型コンパイル) がデフォルトに なったため
  38. 38. © 2020 NTT DATA Corporation 38 バイトコード C1⽣成機械語 C2⽣成機械語 Tiered Compilation概要 • C1とC2の両⽅を使う
  39. 39. © 2020 NTT DATA Corporation 39 JITコンパイルのログを 出⼒してみよう︕
  40. 40. © 2020 NTT DATA Corporation 40 JITコンパイルのログ設定 • 以下のオプションを付ける • -XX:+PrintCompilation • コンソールにコンパイルログを出⼒する
  41. 41. © 2020 NTT DATA Corporation 41 PrintCompilationの出⼒ 181 416 4 java.lang.AbstractStringBuilder::append (45 bytes) 182 417 ! 3 java.util.zip.InflaterInputStream::read (138 bytes) 182 420 n 0 java.util.zip.Inflater::inflateBytesBytes (native) 182 418 3 java.util.zip.InflaterInputStream::ensureOpen (18 bytes) 182 419 3 java.io.RandomAccessFile::seek (22 bytes) 183 421 3 java.util.WeakHashMap::getTable (9 bytes) 183 422 ! 3 java.util.WeakHashMap::expungeStaleEntries (139 bytes) 184 423 3 java.util.WeakHashMap::indexFor (6 bytes) 184 424 3 java.io.File::isInvalid (48 bytes) 184 427 3 java.util.zip.ZipUtils::CENSIZ (9 bytes) 184 428 3 java.io.UnixFileSystem::normalize (41 bytes) 185 429 3 java.util.zip.ZipFile::ensureOpen (40 bytes) 185 425 1 java.nio.HeapByteBuffer::isDirect (2 bytes) 185 431 s 3 jdk.internal.loader.Resource::cachedInputStream (20 bytes)
  42. 42. © 2020 NTT DATA Corporation 42 デモ SpringBoot起動での JITコンパイルログ出⼒
  43. 43. © 2020 NTT DATA Corporation 43 実際のJITコンパイルログ 32 5 3 java.lang.String::coder (15 bytes) ... 150 235 4 java.lang.String::coder (15 bytes) 151 5 3 java.lang.String::coder (15 bytes) made not entrant 経過時間 コンパイルID 最適化レベル 破棄した コンパイルした メソッドのバイト数
  44. 44. © 2020 NTT DATA Corporation 44 JITコンパイルの最適化レベル 最適化レベル: 0 インタプリタ ⼀般的ケース プロファイリング なし ベーシック カウンタのみ 詳細 3 4 C2が詰まっているケース 0 2 43 効果が薄いメソッドの ケース 0 1 3 C1コンパイラ C2
  45. 45. © 2020 NTT DATA Corporation 45 JITコンパイラの最適化レベル 0 インタプリタ実⾏ 1 C1 (プロファイリングなし) 2 C1 (ベーシックカウンタのみ プロファイリング) 3 C1 (完全なプロファイリング) 4 C2
  46. 46. © 2020 NTT DATA Corporation 46 $ javap -c --module java.base java.lang.String ... byte coder(); Code: 0: getstatic 3: ifeq 6: aload_0 7: getfield 10: goto 13: iconst_1 14: ireturn メソッドのバイト数 String#coder()は 15バイトのメソッド︕
  47. 47. © 2020 NTT DATA Corporation 47 再掲︓実際のJITコンパイルログ 32 5 3 java.lang.String::coder (15 bytes) ... 150 235 4 java.lang.String::coder (15 bytes) 151 5 3 java.lang.String::coder (15 bytes) made not entrant 経過時間 コンパイルID 最適化レベル 破棄した コンパイルした メソッドのバイト数
  48. 48. © 2020 NTT DATA Corporation 48 JITコンパイルのログ設定 • 以下のオプションを付ける • -XX:+PrintCompilation • コンソールにコンパイルログを出⼒する • Unified JVM Loggingでも出⼒できます • -Xlog:jit+compilation=debug
  49. 49. © 2020 NTT DATA Corporation 49 JITコンパイラが コンパイルしたメソッドは わかったけど ⽣成した機械語も⾒たい︕
  50. 50. © 2020 NTT DATA Corporation 50 たとえばこういったケース • あるメソッドがJITコンパイルされているか 確認したい • パフォーマンスに⼤きく影響するメソッドである場合 • 実⾏中のどの時点でJITコンパイルされたかが重要な場合 • オプションの変更による影響を確認する場合
  51. 51. © 2020 NTT DATA Corporation 51 HSDIS(HotSpot Disassembler) • JIT⽣成の機械語をアセンブリに変換して 出⼒するライブラリ • HotSpot VM⽤(通常のOpenJDKとOracle JDK) • OpenJDKに含まれている • src/utils/hsdis ディレクトリで⾃分でビルドする • ビルド⼿順参考︓https://www.slideshare.net/nttdata-tech/java-maximize-cpu-2019-nttdata-suenaga • HSDISをビルドし、JDKに配置する • [JAVA_HOME]/lib ディレクトリ • 以下のオプションを付けて起動する • -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
  52. 52. © 2020 NTT DATA Corporation 52 HSDISの出⼒ Demo2.workload(I)I (Demo2.workload(int)) [0x000000010b997b20, 0x000000010b997b60] 64 bytes [Entry Point] [Constants] # {method} {0x000000012709faf8} 'workload' '(I)I' in 'Demo2' # this: rsi:rsi = 'Demo2' # parm0: rdx = int # [sp+0x10] (sp of caller) 0x000000010b997b20: mov 0x8(%rsi),%r10d 0x000000010b997b24: shl $0x3,%r10 0x000000010b997b28: cmp %r10,%rax 0x000000010b997b2b: jne 0x000000010b92f000 ; {runtime_call ic_miss_stub} 0x000000010b997b31: nop 0x000000010b997b32: nopl 0x0(%rax) 0x000000010b997b39: nopl 0x0(%rax) [Verified Entry Point] 0x000000010b997b40: nopl 0x0(%rax,%rax,1) 0x000000010b997b45: inc %edx ;*iadd {reexecute=0 rethrow=0 return_oop=0} ; - Demo2::workload@2 (line 9) 0x000000010b997b47: mov %edx,%eax ;*ireturn {reexecute=0 rethrow=0 return_oop=0}
  53. 53. © 2020 NTT DATA Corporation 53 デモ SpringBoot起動時の アセンブリ表⽰
  54. 54. © 2020 NTT DATA Corporation 54 読みやすいとは ⾔えません
  55. 55. © 2020 NTT DATA Corporation 55 出⼒するメソッドを指定できる • CompileOnlyオプションを付与する • -XX:CompileOnly=String::startsWith -XX:CompileCommand=quiet • コンパイラディレクティブを使う 1. JSONファイルで対象を指定する 2. -XX:+UnlockDiagnosticVMOptions -XX:CompilerDirectivesFile=directive.json [ { match: "java/lang/String.*", PrintAssembly: true } ]
  56. 56. © 2020 NTT DATA Corporation 56 参考︓JITWatch • JITコンパイルログの解析と可視化ができる • https://github.com/AdoptOpenJDK/jitwatch
  57. 57. © 2020 NTT DATA Corporation 57 Javaバイトコードを 機械語にする プロセスは︖
  58. 58. © 2020 NTT DATA Corporation 58 JITコンパイルのプロセス Java バイトコード IR (中間表現) 機械語 最適化を適⽤し、 IRを変更するサイクル を繰り返す ① ③ ②
  59. 59. © 2020 NTT DATA Corporation 59 IR(Intermediate Representation) • コードをデータ構造で表現する • JVMでは、グラフで表現している • プログラムの依存をグラフにする • 通称 IRグラフ
  60. 60. © 2020 NTT DATA Corporation 60 例: x + y をグラフにする
  61. 61. © 2020 NTT DATA Corporation 61 例: getX() + getY() をグラフにする
  62. 62. © 2020 NTT DATA Corporation 62 例: メソッドの呼び出し順序を考慮 ⻩⾊が実⾏順序、緑⾊がデータフロー
  63. 63. © 2020 NTT DATA Corporation 63 JVMのIRグラフを ⾒てみよう (ただし、C2ではなく GraalVM JITコンパイラ)
  64. 64. © 2020 NTT DATA Corporation 64 IdealGraphVisualizer IRグラフ可視化ツール • ただし、GraalVM JITコンパイラ⽤ • -Dgraal.Dump=:1 オプションをつけて実⾏する • https://www.graalvm.org/docs/reference-manual/tools/#ideal-graph-visualizer
  65. 65. © 2020 NTT DATA Corporation 65 参考: C2とGraalVM JITコンパイラ • C2 • OpenJDKのデフォルト • C++で書かれている • GraalVM JITコンパイラ • GraalVMのデフォルト • Javaで書かれている • OpenJDKにもポートされている (10以降) • JEP 317: Experimental Java-Based JIT Compiler
  66. 66. © 2020 NTT DATA Corporation 66 デモ IRグラフをダンプして IGVで表⽰する
  67. 67. © 2020 NTT DATA Corporation 67 JITコンパイルでの 最適化とは、 このグラフに対する パターンマッチとなる イメージ
  68. 68. © 2020 NTT DATA Corporation 68 ものすごくラフな例 Aノード Bノード Cノード Dノード Dノード Eノード 最適化パターンにマッチ︕
  69. 69. © 2020 NTT DATA Corporation 69 JITコンパイラの構成 バイト コード フロント エンド バック エンド 機械語
  70. 70. © 2020 NTT DATA Corporation 70 フロントエンド • ハードウェアから独⽴ • バイトコードからIRを⽣成する • IRに最適化をほどこす • IRは、HIRと呼ぶ • High-Level IR: ⾼⽔準中間表現
  71. 71. © 2020 NTT DATA Corporation 71 バックエンド • ハードウェアに依存 • レジスタを割り当てる • IRから機械語を⽣成する • IRはLIRと呼ぶ • Low-Level IR: 低⽔準中間⾔語
  72. 72. © 2020 NTT DATA Corporation 72 JITコンパイルの処理の流れ クラス ロード バイト コード HIR HIR LIR LIR 機械語 コード フロントエンド バックエンド HIR⽣成 最適化 レジスタ割当 コード⽣成
  73. 73. © 2020 NTT DATA Corporation 73 o.g.compiler.core.GraalCompiler public static <T extends CompilationResult> T compile(Request<T> r) { ... emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, null, r.lirSuites); ... }
  74. 74. © 2020 NTT DATA Corporation 74 最適化 • メソッドのインライン化 • ループアンロール • デッドコード削除 • ロック粗粒化 / ロック省略 • エスケープ解析 (厳密には最適化ではない) • などなど多数
  75. 75. © 2020 NTT DATA Corporation 75 ホットパスでのコンパイル ノード ノード ノード ノード プロファイル結果から、 左ルートを前提とした コードを⽣成する
  76. 76. © 2020 NTT DATA Corporation 76 実⾏が右ルートに⾏く場合は︖ ノード ノード ノード ノード ⽣成したコードにある トラップに⼊る
  77. 77. © 2020 NTT DATA Corporation 77 脱最適化: Deoptimization • JITコンパイラが⽴てた前提から 外れた実⾏となった場合 • if – else if でまれな経路に⼊る • クラスロードでインタフェースの実装クラスが増える • 機械語の実⾏から インタプリタでの実⾏に戻る
  78. 78. © 2020 NTT DATA Corporation 78 JITコンパイルのライフサイクル インタプリタ コードキャッシュ C1 C2 脱最適化
  79. 79. © 2020 NTT DATA Corporation 79 コードキャッシュ • 機械語コードは CodeCache (C++オブジェクト)内に 配置する • -XX:ReservedCodeCacheSize でキャッシュサイズを指定 • デフォルトサイズは、240MB
  80. 80. © 2020 NTT DATA Corporation 80 Java HotSpot(TM) 64-Bit Server VM warning: CodeCache is full. Compiler has been disabled. Java HotSpot(TM) 64-Bit Server VM warning: Try increasing the code cache size using -XX:ReservedCodeCacheSize= CodeCache: size=2496Kb used=1980Kb max_used=1983Kb free=515Kb bounds [0x0000000103db8000, 0x0000000104028000, 0x0000000104028000] total_blobs=1104 nmethods=623 adapters=288 compilation: disabled (not enough contiguous free space left) コードキャッシュあふれ
  81. 81. © 2020 NTT DATA Corporation 81 アプリケーションの パフォーマンスが 低下する
  82. 82. © 2020 NTT DATA Corporation 82 今回扱っていない話題 • コンパイルキュー • OSR: On Stack Replacement • 各最適化⼿法の詳細 • SSA: Static Single Assignment • レジスタ割付のアルゴリズム • Linear Scan Register Allocation
  83. 83. © 2020 NTT DATA Corporation 83 まとめ • JITコンパイラ • バイトコードを機械語に変換する • HotSpot VMのJITコンパイラ • C1とC2でTiered Compilation • HSDIS(+JITWatch) • JIT⽣成コードを実際に⾒れる
  84. 84. © 2020 NTT DATA Corporation本資料に記載されている会社名、商品名、⼜はサービス名は、各社の登録商標⼜は商標です

×