SlideShare una empresa de Scribd logo
1 de 39
Descargar para leer sin conexión
x86 向け Hotspot の気持ちになって考える
              JIT コンパイラの適応的
               最適化について
Outline
1. JIT コンパイラの気持ちになって
2. 適応的最適化と上手に付き合う
3. Hotspot の x86 向け最適化
                           2012/06/16 X86/X64 最適化勉強会 4
                     nothingcosmos <nothingcosmos@gmail.com>
プロフィール
   x86 最適化勉強会は 1 回目以来 (icc を使う )
   ソフトウェアエンジニア (SI 系 ) Excel がともだち
    昔コンパイラを作る仕事をしていました。
   ここ 1 年は JIT コンパイラを搭載した
    VM に興味が向いてました。
    LLVM­­>Hotspot(OpenJDK)­­>V8­­>dartvm
   決して Oracle の回し者ではありませんので、、
注意点
   JIT コンパイラの話は薀蓄程度のものです。
    JIT コンパイラとともだちになっても、あまり効果ない。
   GC の話は無いです。
    JVM のパフォーマンスは GC のチューニングに依存。
   Oracle さんの GC セミナーとか勉強になるんじゃ
用語説明
   用語説明
   Hotspot  JVM の実装。今回は OpenJDK7 を指します。
   Client コンパイラ [­client]  C1
   Server コンパイラ [­server]  C2 opto
   Devirtualization  脱仮想化 仮想関数呼び出しを置き換える。
   Deoptimization  脱最適化 インタプリタ実行に戻す。
JIT コンパイラの概要
   const なんとかさんが、なんとかしてくれる疑惑。
Hotspot の概要
   最初は bytecode をインタプリタ実行する。
   条件にマッチした method を JIT コンパイル
          (1)  よく回るループを内包した method
           backword branch count
          (2)  よく呼び出される method
           method invocation count
   JIT コンパイラは、実行時の定常状態 (steady state) を、
    測定、仮定し、最適化する。
   AOT コンパイラには無理だけど、代わりに手続き間最適化が可能。
    ※ リフレクションや動的コード生成 / 読み込みが無いからね。
Hotspot の概要
                         JIT コンパイル
              プロファイル情報       を指示
                を通知


 Runtime




コンパイル済み Asm
適応的最適化の概要
   Hotspot の特徴。何に適応するのか
   (1) 実行時の CPU アーキテクチャに適応する。
         x86 の SSE42 や AVX
   (2) 実行時の環境に適応する。
         クラスローダーや読み込み済みのクラスを監視する。
   (3) 実行するプログラムに適応する。
         インタプリタ実行時にプロファイルを取る。
   上記情報は、 JIT コンパイル時に活用して最適化する。
適応的最適化の概要
               プロファイル情報
                 を参照
                                        JIT コンパイル
                             プロファイル情報       を指示
                               を通知


                Runtime
クラスロードを
  通知




 コンパイル済みの
インストール or 破棄                             SSE 使うコード
                                            を生成
               コンパイル済み Asm
JIT コンパイラの気持ちになって
   JavaOne Tokyo 2012
          How to Write Low Latency Java Applications
          What you need to know about JIT compilation
   ポイント
          Optimization impact from "method inlining"
JIT コンパイラの気持ちになって
   JavaOne Tokyo 2012
          How to Write Low Latency Java Applications
          What you need to know about JIT compilation
   ポイント
          Optimization impact from "method inlining"


結論
●

● JIT コンパイラのことなんて気にしなくていいよ(^^;

● 後でボトルネック調査して最適化しろ
Method inlining と脱仮想化について

                                    Product P = ...
   interface Product {              ...
      public void invoke();         P.invoke();// 仮想関数呼び出し
   }
                                    ...


class ProductA{
   public void invoke() {
     //...
     System.out.println("hello");
   }
}
Method inlining と脱仮想化について

                               Product P = ...
   interface Product {         ...
      public void invoke();    P.invoke();// 仮想関数呼び出し
   }
                               ...
                     呼び出し先が一意に決まる
                      直接呼び出しに置換して
                      インライン展開しちゃう。

class ProductA{
   public void invoke() {
                                             Product P = ...
     //...                                   ...
     System.out.println("hello");            { //ProductA.invoke();
   }                                             //...
}
                   Direct devirtialization       System.out.println("hello");
                      Method inlining
                                             }
                                             ...
Hotspot の direct devirtualization
   bytecode レベルで、 invokevirtual もしくは invokeinterface で、
      呼び出し候補が 1 つだけなら、
          invokevirtual or invokeinterface­­>invokespecial に置換
          親クラスが abstract だったらアウト。
          invokestatic 、 invokespecial 、 invokevirtual かつ final
             だったら inline 展開を試行
   投機的に実行する場合、 dependency で条件
     (assert_unique_concrete_method) を登録
   Classloader が interface Product を継承する他のクラスを読み
      込んだら、 mutex で VM 全体を止めて脱最適化を行う。
Method inlining と脱仮想化について
                   public interface Product {
                     public void invoke();
                   }
                                                             クラスローダーが
                                                            後から読み込んだら
   Interface を
 実装するクラスが
  複数あったら?
                                       public class ProductB{
                                         public void invoke() {
                                            //...
                                            System.out.println(”world");
   public class ProductA{                }
     public void invoke() {            }
        //...
        System.out.println("hello");
     }
   }
C1 の脱仮想化について
               Dependency に
                脱仮想化した
                メソッドを登録
                               仮想関数の
                              クラス階層を解析
  Runtime




 コンパイル済み Asm
C1 の脱仮想化について
     Dependency              Dependency に
     リストを走査                   脱仮想化した
                              メソッドを登録
                                             仮想関数の
                                            クラス階層を解析
                  Runtime
クラスロードを
  通知




 コンパイル済みの
インストール or 破棄

               コンパイル済み Asm
Shark の脱仮想化について
     Dependency               Dependency に
     リストを走査                    脱仮想化した
                               メソッドを登録
                                                    仮想関数の
                                                   クラス階層を解析
                  Runtime
クラスロードを
  通知
                                                 Shark     LLVM




                             Bytecode から LLVM Bitcode に変換する際に、
                             Invokevirtual を直接関数呼び出しに変換したり
 コンパイル済みの                                GC 用の safepoint や
インストール or 破棄                     exceptionhandling を bitcode に挿入

               コンパイル済み Asm
Hotspot の JIT コンパイラ
                AbstractCompiler




C1Compiler
        SharkCompiler        C2Compiler
C2 の脱仮想化について
   C2 の脱仮想化は、 guarded deviratualization
   ガード (nullcheck, typecheck) を挿入して脱仮想化を試行する。
   ガードの else 節で脱最適化もしくは仮想関数呼び出しを挿入
   そのため、 C1 と異なりクラスローダで読み込むのは大丈夫。
          ガードの else 節の実行に注意。
C2 の脱仮想化について
      Product P = xxx;
      …
      ...
      P->invoke();//interface 越しに仮想関数呼び出し
      //ProductA が 100 回、 ProductB が 10 回、、?

   インタプリタは P­>invoke() で何を呼び出したのか記録する。
   Interface Product を実装したクラスを解析する。
   呼び出し候補が 1 種。 moro­morphic call
   呼び出し候補が 2 種。 bi­morphic call
   呼び出し候補が 3 種以上。 mega­morphic call
C2 の脱仮想化について
     Mono­morphic call
             呼び出し候補が1つだけ。呼び出し履歴が1種だけ。


mono_morphic = P->invoke;
if (nullcheck(mono_morhpic) &&
      typecheck(invokeA, mono_morphic)) {
      //invokeA() // インライン展開を試行する
      …
} else {
      Uncommon_trap();// 脱最適化を試行する。
}
C2 の脱仮想化について
     Bi­morphic call
             呼び出し候補が 2 つ。呼び出し履歴が 2 種だけ。
bi_morphic = P->invoke;
if (nullcheck(bi_morphic) &&
      typecheck(invokeA, bi_morphic)) {
      //invokeA();// インライン展開を試行する
      ...
} else if(nullcheck(bi_morphic) &&
      typecheck(invokeB, bi_morphic) {
      invokeB();// インライン展開を試行しない。
} else {
      Uncommon_trap();// 脱最適化を試行する。
}
C2 の脱仮想化について
     Mega­morphic call
             呼び出し候補が 3 つ以上。呼び出し履歴が 3 種以上。


//invokeA が 90% の確率で呼び出される場合に限る
mega_morphic = P->invoke;
if (nullcheck(mega_morphic) &&
      typecheck(invokeA, mega_morphic)) {
      //invokeA(); // インライン展開を試行する
      ...
} else {
      P->invoke();//vtable を引いて仮想関数を呼び出す
}
C2 の脱仮想化について
     Mega­morphic call
             呼び出し候補が 3 つ以上。呼び出し履歴が 3 種以上。




// プロファイルの結果、呼び出し先に偏りがない
P->invoke();//vtable を引いて仮想関数を呼び出す
脱仮想化のベンチマーク結果
   10 割で呼ばれるメソッドと、
    3 種 3 割で均等に呼ばれる仮想関数
    呼び出しを 1000,000 回繰り返す。
   10 割で呼ばれるメソッド、 0.24 秒
   3 割で均等に呼ばれる仮想関数 1.2 秒
   Corei7 で 3.4GHz なので、仮想関数呼び出しは 1 回あたり
    3400clock 程度を消費している?
適応的最適化と上手に付き合う?
   JIT コンパイラは頑張ってくれてるけど、俺はどうすれば???
   目的の関数が inline 展開されているか確認する。
         処理のボトルネックに仮想関数呼び出しを使わない。
         インスタンス化するのは一種類までに絞る。
         JIT コンパイルされた最良なコードが実行されているか
            trace する。
   目的の関数が JIT コンパイルされているか確認する。
    jdk1.5 とか結構はまる。
   Oracle さんにサポートツール沢山あるんじゃないかな?
オプションで確認する。
   ­XX:+UnlockDiagnosticVMOptions ­XX:+PrintInlining
   ­XX:+PrintCompilation
   ­XX:+PrintOptoAssembly
   JVM のオプションは下記スライドが詳しい。
    Øredev 2011 ­ JVM JIT for Dummies (What the JVM Does 
      With Your Bytecode When You're Not Looking)
JIT コンパイラの生成したコード
    JVM が JIT コンパイルしたアセンブラを読むのは
     結構おもろい
    OpenJDK を debug 版でビルドしてチャレンジ
     ­XX:+PrintOptoAssembly
                                                                   C2 で JIT コンパイル
public static long testCompare() {                                  52byte
  long sum=0;
  String base = new String("abcdefghijklmnopqrstuvwxyz5555");
  for (int i=0; i<TEST_LENGTH; i++) {
    sum += base.compareTo(sarray.get(i%INIT_LENGTH));
  }
  return sum;
}
共通のループ前準備




   OSR の後処理



   ガチガチチェックの
 1 週しか回らないループ



  真のカーネルループ



   後処理ループ。
カーネルループと変わらん。



     脱最適化ゾーン
Hotspot の x86 向け最適化
   JVM の低レイヤのお仕事。バイナリアン向け。
   openjdk7/hotspot/src/cpu/x86/vm
   MacroAssembler で書かれてる。 assembler_x86.cpp
   専用の vmIntrinsics を用意して x86 向けに最適化
           Prefetch の自動挿入
           Cmpxchg で cas してみたり
           文字列処理を自動で SSE42 使って高速化
Hotspot の x86 向け最適化
       bytecode              invokevirtual
                         String.equals(String)



                             invokevirtual
       jvm の中        vmIntrinsics(string_equals)




       IdealNode     callNode(StrEqualsNode)



                          MacroAssembler
       MachNode        char_arrays_equals()


        ptest 命令使って
              simd
Hotspot の x86 向け最適化
   src/share/vm/opto の下の見どころ
          macro.cpp   メモリアロケーションや TLAB や lock
   src/cpu/x86/vm の下の見どころ
          MacroAssembler::string_indexof/string_indexofC8
          MacroAssembler::string_compare
          MacroAssembler::char_arrays_equals
          MacroAssembler::biased_locking_enter
          MacroAssembler::g1_write_barrier_pre/post
prefetch の自動挿入
System.out.printf("%dn", sum);
149 B28: # B47 B29 <- B35 B27 Freq: 0.64794
149 MOV ECX, Thread::current()
155 MOV EAX,[ECX + #68]
158 LEA EBX,[EAX + #16]
                                                           昔は Prefetcht0 を自動挿入する
15b MOV EDI,java/lang/Class:exact *
160 MOV EDI,[EDI + #108] ! Field java/lang/System.out       ケースもあったような気が。
163 CMPu EBX,[ECX + #76]
166 Jnb,u B47 P=0.000100 C=-1.000000                       文字列系の処理は、 prefetchnta
166
16c B29: # B30 <- B28 Freq: 0.647875
16c MOV [ECX + #68],EBX
                                                            でキャッシュ汚染を最小化
16f PREFETCHNTA [EBX + #192]
176 MOV [EAX],0x00000001
17c PREFETCHNTA [EBX + #256]
183 MOV [EAX + #4],precise klass [Ljava/lang/Object;:      Prefetchnta は L1 キャッシュのみ
18a PREFETCHNTA [EBX + #320]
191 MOV [EAX + #8],#1
198 PREFETCHNTA [EBX + #384]
                                                            他のキャッシュには乗せない。
19f MOV [EAX + #12],#0
1a6 MOV [ESP + #16],EDI
String.indexOf(String)
                                                                             pcmpestri の mode=0xd
void MacroAssembler::string_indexof(
...
  // Scan string for start of substr in 16-byte vectors
                                                                              1100: 部分文字列比較
  bind(SCAN_TO_SUBSTR);
  assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");                  01:unsigned short 比較
  pcmpestri(vec, Address(result, 0), 0x0d);
  jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1                        string_indexofC8 っていう
  subl(cnt1, 8);
  jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string
  cmpl(cnt1, cnt2);                                                           特殊版もある。
  jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring
  addptr(result, 16);                                                        herumi さんの strstr を
  bind(ADJUST_STR);                                                           参照。
  cmpl(cnt1, 8); // Do not read beyond string
  jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR);
                                                                             indexOf(int) ではない。
...
String.compareTo(String)
                                                                        pcmpestri の mode=019
void MacroAssembler::string_compare(
…
    int stride = 8;
                                                                         010000:negative polarity
...
    bind(COMPARE_WIDE_VECTORS);                                              1000:equal each
    movdqu(vec1, Address(str1, result, scale));
    pcmpestri(vec1, Address(str2, result, scale), pcmpmask);                     01:unsigned short 比較
    // After pcmpestri cnt1(rcx) contains mismatched element index

      jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1
                                                                        herumi さんの SSE4.2
      addptr(result, stride);
      subptr(cnt2, stride);                                              文字列処理を参照。
      jccb(Assembler::notZero, COMPARE_WIDE_VECTORS);

      // compare wide vectors tail
                                                                        返り値は 0, >0, <0 の
      testl(result, result);
      jccb(Assembler::zero, LENGTH_DIFF_LABEL);                          いずれかなので、
...
                                                                         出口は多少複雑。
String.equals(String), Arrays.equals()
// Compare char[] arrays aligned to 4 bytes or substrings.
void MacroAssembler::char_arrays_equals(
…                                                                                  pxor, ptest を使って、
   shll(limit, 1);    // byte count != 0
   movl(result, limit); // copy                                                     128bit 単位で等しいか判定
   // Compare 16-byte vectors
   andl(result, 0x0000000e); // tail count (in bytes)
   andl(limit, 0xfffffff0); // vector count (in bytes)
                                                                                   String でも、 Arrays でも、
   jccb(Assembler::zero, COMPARE_TAIL);
                                                                                    左記の SSE42 が呼ばれる。
  lea(ary1, Address(ary1, limit, Address::times_1));
  lea(ary2, Address(ary2, limit, Address::times_1));
  negptr(limit);
                                                                                   最後に端数を比較する。
  bind(COMPARE_WIDE_VECTORS);
  movdqu(vec1, Address(ary1, limit, Address::times_1));
  movdqu(vec2, Address(ary2, limit, Address::times_1));
  pxor(vec1, vec2);

  ptest(vec1, vec1);                             testl(result, result);
  jccb(Assembler::notZero, FALSE_LABEL);         jccb(Assembler::zero, TRUE_LABEL);
  addptr(limit, 16);
  jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); movdqu(vec1, Address(ary1, result, Address::times_1, -16));
                                                 movdqu(vec2, Address(ary2, result, Address::times_1, -16));
                                                 pxor(vec1, vec2);

                                                              ptest(vec1, vec1);
                                                              jccb(Assembler::notZero, FALSE_LABEL);
                                                              jmpb(TRUE_LABEL);
                                                             ...
ベンチマーク結果
   SSE42 の有無を適当にベンチマーク ( ループを 100M 回 )
    ループのオーバーヘッドは取り除いています。
    データが適当なので、数値の信頼性ないですが雰囲気だけ。
                       SSE42 なし     SSE42 あり     差 (sec)
     compareTo                2.421        1.156           1.265

     indexOf(String)          2.433         1.186           1.247
     indexOf(int)              1.31         1.327          -0.017
     indexOfC8                2.042         0.857           1.185
     charArrayEqual           0.826         0.446            0.38
     s
     String.equals           -0.001         0.002          -0.003
おまけ (OpenJDK8)
   OS 対応
         BSD へ対応
   CPU 依存部分
         AVX へ対応
         高速な macro を追加 fast_pow(), fast_exp()
         FPInstruction を使って計算した log を元に pow と exp
   C2 コンパイラ
         OptimizePtrCompare オプションが追加。デフォルト true
         EscapeAnalysis が大幅改良。 PtrCompare でごにょ
         nest した lock/unlock の除去。 MemBarNode が増えたり

Más contenido relacionado

La actualidad más candente

Vivado hls勉強会4(axi4 master)
Vivado hls勉強会4(axi4 master)Vivado hls勉強会4(axi4 master)
Vivado hls勉強会4(axi4 master)marsee101
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
PHPとシグナル、その裏側
PHPとシグナル、その裏側PHPとシグナル、その裏側
PHPとシグナル、その裏側do_aki
 
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係Mr. Vengineer
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説do_aki
 
php-src の歩き方
php-src の歩き方php-src の歩き方
php-src の歩き方do_aki
 
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 とPHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 とdo_aki
 
Synthesijer jjug 201504_01
Synthesijer jjug 201504_01Synthesijer jjug 201504_01
Synthesijer jjug 201504_01Takefumi MIYOSHI
 
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるKoichi Sakata
 
Vivado hlsのシミュレーションとhlsストリーム
Vivado hlsのシミュレーションとhlsストリームVivado hlsのシミュレーションとhlsストリーム
Vivado hlsのシミュレーションとhlsストリームmarsee101
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 TipsTakaaki Suzuki
 
Vivado hls勉強会3(axi4 lite slave)
Vivado hls勉強会3(axi4 lite slave)Vivado hls勉強会3(axi4 lite slave)
Vivado hls勉強会3(axi4 lite slave)marsee101
 
Task Spooler を試した
Task Spooler を試したTask Spooler を試した
Task Spooler を試したy-uti
 
C++ AMPを使ってみよう
C++ AMPを使ってみようC++ AMPを使ってみよう
C++ AMPを使ってみようOsamu Masutani
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1信之 岩永
 

La actualidad más candente (20)

Vivado hls勉強会4(axi4 master)
Vivado hls勉強会4(axi4 master)Vivado hls勉強会4(axi4 master)
Vivado hls勉強会4(axi4 master)
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
PHPとシグナル、その裏側
PHPとシグナル、その裏側PHPとシグナル、その裏側
PHPとシグナル、その裏側
 
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
Altera SDK for OpenCL解体新書 : ホストとデバイスの関係
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
 
Inside FastEnum
Inside FastEnumInside FastEnum
Inside FastEnum
 
php-src の歩き方
php-src の歩き方php-src の歩き方
php-src の歩き方
 
PHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 とPHP と SAPI と ZendEngine3 と
PHP と SAPI と ZendEngine3 と
 
Synverll
SynverllSynverll
Synverll
 
Synthesijer jjug 201504_01
Synthesijer jjug 201504_01Synthesijer jjug 201504_01
Synthesijer jjug 201504_01
 
Let's play with Goldfish
Let's play with GoldfishLet's play with Goldfish
Let's play with Goldfish
 
最速C# 7.x
最速C# 7.x最速C# 7.x
最速C# 7.x
 
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
 
Vivado hlsのシミュレーションとhlsストリーム
Vivado hlsのシミュレーションとhlsストリームVivado hlsのシミュレーションとhlsストリーム
Vivado hlsのシミュレーションとhlsストリーム
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
Vivado hls勉強会3(axi4 lite slave)
Vivado hls勉強会3(axi4 lite slave)Vivado hls勉強会3(axi4 lite slave)
Vivado hls勉強会3(axi4 lite slave)
 
Task Spooler を試した
Task Spooler を試したTask Spooler を試した
Task Spooler を試した
 
Hls friends 20161122.key
Hls friends 20161122.keyHls friends 20161122.key
Hls friends 20161122.key
 
C++ AMPを使ってみよう
C++ AMPを使ってみようC++ AMPを使ってみよう
C++ AMPを使ってみよう
 
C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 

Destacado

JITコンパイルはじめの一歩
JITコンパイルはじめの一歩JITコンパイルはじめの一歩
JITコンパイルはじめの一歩Koichi Sakata
 
Marketing in uncertain times
Marketing in uncertain timesMarketing in uncertain times
Marketing in uncertain timesKantar
 
Luke and rebecca pitch
Luke and rebecca pitchLuke and rebecca pitch
Luke and rebecca pitchsalesianas2011
 
The Trion Towers @ Fort Bonifacio Global City
The Trion Towers @ Fort Bonifacio Global CityThe Trion Towers @ Fort Bonifacio Global City
The Trion Towers @ Fort Bonifacio Global CityNorman Garcia
 
Implikasi sejarah perkembangan persekolahan kepada penentuan hala tujuan
Implikasi sejarah perkembangan persekolahan kepada penentuan hala tujuanImplikasi sejarah perkembangan persekolahan kepada penentuan hala tujuan
Implikasi sejarah perkembangan persekolahan kepada penentuan hala tujuanAmir Ibrahim
 
Promosi t shirt
Promosi t shirtPromosi t shirt
Promosi t shirtJay
 
Vrundavan Apartments at Sangamner
Vrundavan Apartments at SangamnerVrundavan Apartments at Sangamner
Vrundavan Apartments at Sangamnervasturekha
 
ماهو الطاغوت
ماهو الطاغوتماهو الطاغوت
ماهو الطاغوتjaljasir
 
Fungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue Howard
Fungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue HowardFungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue Howard
Fungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue HowardGraham Atherton
 
Reaching Younger Distance Learners through Technology & Social Media, Indones...
Reaching Younger Distance Learners through Technology & Social Media, Indones...Reaching Younger Distance Learners through Technology & Social Media, Indones...
Reaching Younger Distance Learners through Technology & Social Media, Indones...Dimas Prasetyo
 
공익마케팅스쿨 1기, 넉달간의 기록
공익마케팅스쿨 1기, 넉달간의 기록공익마케팅스쿨 1기, 넉달간의 기록
공익마케팅스쿨 1기, 넉달간의 기록승훈 오
 
イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~
イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~
イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~InnovationSprint2011
 

Destacado (20)

JITコンパイルはじめの一歩
JITコンパイルはじめの一歩JITコンパイルはじめの一歩
JITコンパイルはじめの一歩
 
M17 2011
M17 2011M17 2011
M17 2011
 
Marketing in uncertain times
Marketing in uncertain timesMarketing in uncertain times
Marketing in uncertain times
 
Luke and rebecca pitch
Luke and rebecca pitchLuke and rebecca pitch
Luke and rebecca pitch
 
The Trion Towers @ Fort Bonifacio Global City
The Trion Towers @ Fort Bonifacio Global CityThe Trion Towers @ Fort Bonifacio Global City
The Trion Towers @ Fort Bonifacio Global City
 
Tprgroup
TprgroupTprgroup
Tprgroup
 
11.1 family.istock proofread
11.1 family.istock proofread11.1 family.istock proofread
11.1 family.istock proofread
 
Lbq 21
Lbq 21Lbq 21
Lbq 21
 
Implikasi sejarah perkembangan persekolahan kepada penentuan hala tujuan
Implikasi sejarah perkembangan persekolahan kepada penentuan hala tujuanImplikasi sejarah perkembangan persekolahan kepada penentuan hala tujuan
Implikasi sejarah perkembangan persekolahan kepada penentuan hala tujuan
 
Promosi t shirt
Promosi t shirtPromosi t shirt
Promosi t shirt
 
Vrundavan Apartments at Sangamner
Vrundavan Apartments at SangamnerVrundavan Apartments at Sangamner
Vrundavan Apartments at Sangamner
 
ماهو الطاغوت
ماهو الطاغوتماهو الطاغوت
ماهو الطاغوت
 
Zorginstelling 3.0
Zorginstelling 3.0Zorginstelling 3.0
Zorginstelling 3.0
 
Media movie
Media movieMedia movie
Media movie
 
Fungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue Howard
Fungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue HowardFungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue Howard
Fungal Research Trust 20th Anniversary Meeting June 2011 - Dr Sue Howard
 
Reaching Younger Distance Learners through Technology & Social Media, Indones...
Reaching Younger Distance Learners through Technology & Social Media, Indones...Reaching Younger Distance Learners through Technology & Social Media, Indones...
Reaching Younger Distance Learners through Technology & Social Media, Indones...
 
A arte de Olbinski
A arte de OlbinskiA arte de Olbinski
A arte de Olbinski
 
공익마케팅스쿨 1기, 넉달간의 기록
공익마케팅스쿨 1기, 넉달간의 기록공익마케팅스쿨 1기, 넉달간의 기록
공익마케팅스쿨 1기, 넉달간의 기록
 
イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~
イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~
イノベーションスプリント2011 infragisticsにおける世界分散アジャイル開発事例~ communication matters ~
 
Cartoons Governo 2012
Cartoons Governo 2012Cartoons Governo 2012
Cartoons Governo 2012
 

Similar a Adaptive optimization of JIT compiler

emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略
emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略
emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略祐司 伊藤
 
社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)Iwana Chan
 
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)Daisuke Ikeda
 
Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義JPCERT Coordination Center
 
関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会Koichi Sakata
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門伸男 伊藤
 
第2回勉強会スライド
第2回勉強会スライド第2回勉強会スライド
第2回勉強会スライドkoturn 0;
 
PEZY-SC programming overview
PEZY-SC programming overviewPEZY-SC programming overview
PEZY-SC programming overviewRyo Sakamoto
 
Vim の開発環境
Vim の開発環境Vim の開発環境
Vim の開発環境eagletmt
 
ATLに見る魔術
ATLに見る魔術ATLに見る魔術
ATLに見る魔術egtra
 
Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方
Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方
Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方tshiroyama
 
Java仮想マシンの実装技術
Java仮想マシンの実装技術Java仮想マシンの実装技術
Java仮想マシンの実装技術Kiyokuni Kawachiya
 
GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化
GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化
GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化Shigeru Tsubota
 
How to Make Own Framework built on OWIN
How to Make Own Framework built on OWINHow to Make Own Framework built on OWIN
How to Make Own Framework built on OWINYoshifumi Kawai
 
Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)Yuji Kubota
 

Similar a Adaptive optimization of JIT compiler (20)

emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略
emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略
emscriptenでC/C++プログラムをwebブラウザから使うまでの難所攻略
 
Spring3.1概要x di
Spring3.1概要x diSpring3.1概要x di
Spring3.1概要x di
 
社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)社内勉強会資料(Varnish Module)
社内勉強会資料(Varnish Module)
 
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)
クラウド環境向けZabbixカスタマイズ紹介(第5回Zabbix勉強会)
 
Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義Javaセキュアコーディングセミナー東京第1回 講義
Javaセキュアコーディングセミナー東京第1回 講義
 
関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会関ジャバ JavaOne Tokyo 2012報告会
関ジャバ JavaOne Tokyo 2012報告会
 
MoteMote Compiler Plugin
MoteMote Compiler PluginMoteMote Compiler Plugin
MoteMote Compiler Plugin
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
 
第2回勉強会スライド
第2回勉強会スライド第2回勉強会スライド
第2回勉強会スライド
 
Cve 2013-0422
Cve 2013-0422Cve 2013-0422
Cve 2013-0422
 
PEZY-SC programming overview
PEZY-SC programming overviewPEZY-SC programming overview
PEZY-SC programming overview
 
Vim の開発環境
Vim の開発環境Vim の開発環境
Vim の開発環境
 
ATLに見る魔術
ATLに見る魔術ATLに見る魔術
ATLに見る魔術
 
Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方
Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方
Backdoor!! vmware-tools と 統合サービスに見るハイパーバイザの呼び出し方
 
Java仮想マシンの実装技術
Java仮想マシンの実装技術Java仮想マシンの実装技術
Java仮想マシンの実装技術
 
Rx java x retrofit
Rx java x retrofitRx java x retrofit
Rx java x retrofit
 
GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化
GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化
GNS3上の仮想アプライアンス+GitLabRunner+BDDによるテスト自動化
 
T93 com入門
T93 com入門T93 com入門
T93 com入門
 
How to Make Own Framework built on OWIN
How to Make Own Framework built on OWINHow to Make Own Framework built on OWIN
How to Make Own Framework built on OWIN
 
Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)Head toward Java 16 (Night Seminar Edition)
Head toward Java 16 (Night Seminar Edition)
 

Más de nothingcosmos

Más de nothingcosmos (6)

2014 dart flight school in Tokyo
2014 dart flight school in Tokyo2014 dart flight school in Tokyo
2014 dart flight school in Tokyo
 
Dart 1.1
Dart 1.1Dart 1.1
Dart 1.1
 
Source Code of Dart
Source Code of DartSource Code of Dart
Source Code of Dart
 
Dart VM Performance
Dart VM PerformanceDart VM Performance
Dart VM Performance
 
DartVM on Android
DartVM on AndroidDartVM on Android
DartVM on Android
 
X86opti01 nothingcosmos
X86opti01 nothingcosmosX86opti01 nothingcosmos
X86opti01 nothingcosmos
 

Adaptive optimization of JIT compiler

  • 1. x86 向け Hotspot の気持ちになって考える JIT コンパイラの適応的 最適化について Outline 1. JIT コンパイラの気持ちになって 2. 適応的最適化と上手に付き合う 3. Hotspot の x86 向け最適化 2012/06/16 X86/X64 最適化勉強会 4 nothingcosmos <nothingcosmos@gmail.com>
  • 2. プロフィール  x86 最適化勉強会は 1 回目以来 (icc を使う )  ソフトウェアエンジニア (SI 系 ) Excel がともだち 昔コンパイラを作る仕事をしていました。  ここ 1 年は JIT コンパイラを搭載した VM に興味が向いてました。 LLVM­­>Hotspot(OpenJDK)­­>V8­­>dartvm  決して Oracle の回し者ではありませんので、、
  • 3. 注意点  JIT コンパイラの話は薀蓄程度のものです。 JIT コンパイラとともだちになっても、あまり効果ない。  GC の話は無いです。 JVM のパフォーマンスは GC のチューニングに依存。  Oracle さんの GC セミナーとか勉強になるんじゃ
  • 4. 用語説明  用語説明  Hotspot  JVM の実装。今回は OpenJDK7 を指します。  Client コンパイラ [­client]  C1  Server コンパイラ [­server]  C2 opto  Devirtualization  脱仮想化 仮想関数呼び出しを置き換える。  Deoptimization  脱最適化 インタプリタ実行に戻す。
  • 5. JIT コンパイラの概要  const なんとかさんが、なんとかしてくれる疑惑。
  • 6. Hotspot の概要  最初は bytecode をインタプリタ実行する。  条件にマッチした method を JIT コンパイル  (1)  よく回るループを内包した method backword branch count  (2)  よく呼び出される method method invocation count  JIT コンパイラは、実行時の定常状態 (steady state) を、 測定、仮定し、最適化する。  AOT コンパイラには無理だけど、代わりに手続き間最適化が可能。 ※ リフレクションや動的コード生成 / 読み込みが無いからね。
  • 7. Hotspot の概要 JIT コンパイル プロファイル情報 を指示 を通知 Runtime コンパイル済み Asm
  • 8. 適応的最適化の概要  Hotspot の特徴。何に適応するのか  (1) 実行時の CPU アーキテクチャに適応する。  x86 の SSE42 や AVX  (2) 実行時の環境に適応する。  クラスローダーや読み込み済みのクラスを監視する。  (3) 実行するプログラムに適応する。  インタプリタ実行時にプロファイルを取る。  上記情報は、 JIT コンパイル時に活用して最適化する。
  • 9. 適応的最適化の概要 プロファイル情報 を参照 JIT コンパイル プロファイル情報 を指示 を通知 Runtime クラスロードを 通知 コンパイル済みの インストール or 破棄 SSE 使うコード を生成 コンパイル済み Asm
  • 10. JIT コンパイラの気持ちになって  JavaOne Tokyo 2012  How to Write Low Latency Java Applications  What you need to know about JIT compilation  ポイント  Optimization impact from "method inlining"
  • 11. JIT コンパイラの気持ちになって  JavaOne Tokyo 2012  How to Write Low Latency Java Applications  What you need to know about JIT compilation  ポイント  Optimization impact from "method inlining" 結論 ● ● JIT コンパイラのことなんて気にしなくていいよ(^^; ● 後でボトルネック調査して最適化しろ
  • 12. Method inlining と脱仮想化について Product P = ... interface Product { ... public void invoke(); P.invoke();// 仮想関数呼び出し } ... class ProductA{ public void invoke() { //... System.out.println("hello"); } }
  • 13. Method inlining と脱仮想化について Product P = ... interface Product { ... public void invoke(); P.invoke();// 仮想関数呼び出し } ... 呼び出し先が一意に決まる 直接呼び出しに置換して インライン展開しちゃう。 class ProductA{ public void invoke() { Product P = ... //... ... System.out.println("hello"); { //ProductA.invoke(); } //... } Direct devirtialization System.out.println("hello"); Method inlining } ...
  • 14. Hotspot の direct devirtualization  bytecode レベルで、 invokevirtual もしくは invokeinterface で、 呼び出し候補が 1 つだけなら、  invokevirtual or invokeinterface­­>invokespecial に置換  親クラスが abstract だったらアウト。  invokestatic 、 invokespecial 、 invokevirtual かつ final だったら inline 展開を試行  投機的に実行する場合、 dependency で条件 (assert_unique_concrete_method) を登録  Classloader が interface Product を継承する他のクラスを読み 込んだら、 mutex で VM 全体を止めて脱最適化を行う。
  • 15. Method inlining と脱仮想化について public interface Product { public void invoke(); } クラスローダーが 後から読み込んだら Interface を 実装するクラスが 複数あったら? public class ProductB{ public void invoke() { //... System.out.println(”world"); public class ProductA{ } public void invoke() { } //... System.out.println("hello"); } }
  • 16. C1 の脱仮想化について Dependency に 脱仮想化した メソッドを登録 仮想関数の クラス階層を解析 Runtime コンパイル済み Asm
  • 17. C1 の脱仮想化について Dependency Dependency に リストを走査 脱仮想化した メソッドを登録 仮想関数の クラス階層を解析 Runtime クラスロードを 通知 コンパイル済みの インストール or 破棄 コンパイル済み Asm
  • 18. Shark の脱仮想化について Dependency Dependency に リストを走査 脱仮想化した メソッドを登録 仮想関数の クラス階層を解析 Runtime クラスロードを 通知 Shark LLVM Bytecode から LLVM Bitcode に変換する際に、 Invokevirtual を直接関数呼び出しに変換したり コンパイル済みの GC 用の safepoint や インストール or 破棄 exceptionhandling を bitcode に挿入 コンパイル済み Asm
  • 19. Hotspot の JIT コンパイラ AbstractCompiler C1Compiler SharkCompiler C2Compiler
  • 20. C2 の脱仮想化について  C2 の脱仮想化は、 guarded deviratualization  ガード (nullcheck, typecheck) を挿入して脱仮想化を試行する。  ガードの else 節で脱最適化もしくは仮想関数呼び出しを挿入  そのため、 C1 と異なりクラスローダで読み込むのは大丈夫。  ガードの else 節の実行に注意。
  • 21. C2 の脱仮想化について Product P = xxx; … ... P->invoke();//interface 越しに仮想関数呼び出し //ProductA が 100 回、 ProductB が 10 回、、?  インタプリタは P­>invoke() で何を呼び出したのか記録する。  Interface Product を実装したクラスを解析する。  呼び出し候補が 1 種。 moro­morphic call  呼び出し候補が 2 種。 bi­morphic call  呼び出し候補が 3 種以上。 mega­morphic call
  • 22. C2 の脱仮想化について  Mono­morphic call  呼び出し候補が1つだけ。呼び出し履歴が1種だけ。 mono_morphic = P->invoke; if (nullcheck(mono_morhpic) && typecheck(invokeA, mono_morphic)) { //invokeA() // インライン展開を試行する … } else { Uncommon_trap();// 脱最適化を試行する。 }
  • 23. C2 の脱仮想化について  Bi­morphic call  呼び出し候補が 2 つ。呼び出し履歴が 2 種だけ。 bi_morphic = P->invoke; if (nullcheck(bi_morphic) && typecheck(invokeA, bi_morphic)) { //invokeA();// インライン展開を試行する ... } else if(nullcheck(bi_morphic) && typecheck(invokeB, bi_morphic) { invokeB();// インライン展開を試行しない。 } else { Uncommon_trap();// 脱最適化を試行する。 }
  • 24. C2 の脱仮想化について  Mega­morphic call  呼び出し候補が 3 つ以上。呼び出し履歴が 3 種以上。 //invokeA が 90% の確率で呼び出される場合に限る mega_morphic = P->invoke; if (nullcheck(mega_morphic) && typecheck(invokeA, mega_morphic)) { //invokeA(); // インライン展開を試行する ... } else { P->invoke();//vtable を引いて仮想関数を呼び出す }
  • 25. C2 の脱仮想化について  Mega­morphic call  呼び出し候補が 3 つ以上。呼び出し履歴が 3 種以上。 // プロファイルの結果、呼び出し先に偏りがない P->invoke();//vtable を引いて仮想関数を呼び出す
  • 26. 脱仮想化のベンチマーク結果  10 割で呼ばれるメソッドと、 3 種 3 割で均等に呼ばれる仮想関数 呼び出しを 1000,000 回繰り返す。  10 割で呼ばれるメソッド、 0.24 秒  3 割で均等に呼ばれる仮想関数 1.2 秒  Corei7 で 3.4GHz なので、仮想関数呼び出しは 1 回あたり 3400clock 程度を消費している?
  • 27. 適応的最適化と上手に付き合う?  JIT コンパイラは頑張ってくれてるけど、俺はどうすれば???  目的の関数が inline 展開されているか確認する。  処理のボトルネックに仮想関数呼び出しを使わない。  インスタンス化するのは一種類までに絞る。  JIT コンパイルされた最良なコードが実行されているか trace する。  目的の関数が JIT コンパイルされているか確認する。 jdk1.5 とか結構はまる。  Oracle さんにサポートツール沢山あるんじゃないかな?
  • 28. オプションで確認する。  ­XX:+UnlockDiagnosticVMOptions ­XX:+PrintInlining  ­XX:+PrintCompilation  ­XX:+PrintOptoAssembly  JVM のオプションは下記スライドが詳しい。 Øredev 2011 ­ JVM JIT for Dummies (What the JVM Does  With Your Bytecode When You're Not Looking)
  • 29. JIT コンパイラの生成したコード  JVM が JIT コンパイルしたアセンブラを読むのは 結構おもろい  OpenJDK を debug 版でビルドしてチャレンジ ­XX:+PrintOptoAssembly  C2 で JIT コンパイル public static long testCompare() { 52byte long sum=0; String base = new String("abcdefghijklmnopqrstuvwxyz5555"); for (int i=0; i<TEST_LENGTH; i++) { sum += base.compareTo(sarray.get(i%INIT_LENGTH)); } return sum; }
  • 30. 共通のループ前準備 OSR の後処理 ガチガチチェックの 1 週しか回らないループ 真のカーネルループ 後処理ループ。 カーネルループと変わらん。 脱最適化ゾーン
  • 31. Hotspot の x86 向け最適化  JVM の低レイヤのお仕事。バイナリアン向け。  openjdk7/hotspot/src/cpu/x86/vm  MacroAssembler で書かれてる。 assembler_x86.cpp  専用の vmIntrinsics を用意して x86 向けに最適化  Prefetch の自動挿入  Cmpxchg で cas してみたり  文字列処理を自動で SSE42 使って高速化
  • 32. Hotspot の x86 向け最適化  bytecode invokevirtual String.equals(String) invokevirtual  jvm の中 vmIntrinsics(string_equals)  IdealNode callNode(StrEqualsNode) MacroAssembler  MachNode char_arrays_equals() ptest 命令使って simd
  • 33. Hotspot の x86 向け最適化  src/share/vm/opto の下の見どころ  macro.cpp   メモリアロケーションや TLAB や lock  src/cpu/x86/vm の下の見どころ  MacroAssembler::string_indexof/string_indexofC8  MacroAssembler::string_compare  MacroAssembler::char_arrays_equals  MacroAssembler::biased_locking_enter  MacroAssembler::g1_write_barrier_pre/post
  • 34. prefetch の自動挿入 System.out.printf("%dn", sum); 149 B28: # B47 B29 <- B35 B27 Freq: 0.64794 149 MOV ECX, Thread::current() 155 MOV EAX,[ECX + #68] 158 LEA EBX,[EAX + #16]  昔は Prefetcht0 を自動挿入する 15b MOV EDI,java/lang/Class:exact * 160 MOV EDI,[EDI + #108] ! Field java/lang/System.out ケースもあったような気が。 163 CMPu EBX,[ECX + #76] 166 Jnb,u B47 P=0.000100 C=-1.000000  文字列系の処理は、 prefetchnta 166 16c B29: # B30 <- B28 Freq: 0.647875 16c MOV [ECX + #68],EBX でキャッシュ汚染を最小化 16f PREFETCHNTA [EBX + #192] 176 MOV [EAX],0x00000001 17c PREFETCHNTA [EBX + #256] 183 MOV [EAX + #4],precise klass [Ljava/lang/Object;:  Prefetchnta は L1 キャッシュのみ 18a PREFETCHNTA [EBX + #320] 191 MOV [EAX + #8],#1 198 PREFETCHNTA [EBX + #384] 他のキャッシュには乗せない。 19f MOV [EAX + #12],#0 1a6 MOV [ESP + #16],EDI
  • 35. String.indexOf(String)  pcmpestri の mode=0xd void MacroAssembler::string_indexof( ... // Scan string for start of substr in 16-byte vectors 1100: 部分文字列比較 bind(SCAN_TO_SUBSTR); assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");     01:unsigned short 比較 pcmpestri(vec, Address(result, 0), 0x0d); jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1  string_indexofC8 っていう subl(cnt1, 8); jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string cmpl(cnt1, cnt2); 特殊版もある。 jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring addptr(result, 16);  herumi さんの strstr を bind(ADJUST_STR); 参照。 cmpl(cnt1, 8); // Do not read beyond string jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR);  indexOf(int) ではない。 ...
  • 36. String.compareTo(String)  pcmpestri の mode=019 void MacroAssembler::string_compare( … int stride = 8; 010000:negative polarity ... bind(COMPARE_WIDE_VECTORS);     1000:equal each movdqu(vec1, Address(str1, result, scale)); pcmpestri(vec1, Address(str2, result, scale), pcmpmask);         01:unsigned short 比較 // After pcmpestri cnt1(rcx) contains mismatched element index jccb(Assembler::below, VECTOR_NOT_EQUAL); // CF==1  herumi さんの SSE4.2 addptr(result, stride); subptr(cnt2, stride); 文字列処理を参照。 jccb(Assembler::notZero, COMPARE_WIDE_VECTORS); // compare wide vectors tail  返り値は 0, >0, <0 の testl(result, result); jccb(Assembler::zero, LENGTH_DIFF_LABEL); いずれかなので、 ... 出口は多少複雑。
  • 37. String.equals(String), Arrays.equals() // Compare char[] arrays aligned to 4 bytes or substrings. void MacroAssembler::char_arrays_equals( …  pxor, ptest を使って、 shll(limit, 1); // byte count != 0 movl(result, limit); // copy 128bit 単位で等しいか判定 // Compare 16-byte vectors andl(result, 0x0000000e); // tail count (in bytes) andl(limit, 0xfffffff0); // vector count (in bytes)  String でも、 Arrays でも、 jccb(Assembler::zero, COMPARE_TAIL); 左記の SSE42 が呼ばれる。 lea(ary1, Address(ary1, limit, Address::times_1)); lea(ary2, Address(ary2, limit, Address::times_1)); negptr(limit);  最後に端数を比較する。 bind(COMPARE_WIDE_VECTORS); movdqu(vec1, Address(ary1, limit, Address::times_1)); movdqu(vec2, Address(ary2, limit, Address::times_1)); pxor(vec1, vec2); ptest(vec1, vec1); testl(result, result); jccb(Assembler::notZero, FALSE_LABEL); jccb(Assembler::zero, TRUE_LABEL); addptr(limit, 16); jcc(Assembler::notZero, COMPARE_WIDE_VECTORS); movdqu(vec1, Address(ary1, result, Address::times_1, -16)); movdqu(vec2, Address(ary2, result, Address::times_1, -16)); pxor(vec1, vec2); ptest(vec1, vec1); jccb(Assembler::notZero, FALSE_LABEL); jmpb(TRUE_LABEL); ...
  • 38. ベンチマーク結果  SSE42 の有無を適当にベンチマーク ( ループを 100M 回 ) ループのオーバーヘッドは取り除いています。 データが適当なので、数値の信頼性ないですが雰囲気だけ。 SSE42 なし SSE42 あり 差 (sec) compareTo 2.421 1.156 1.265 indexOf(String) 2.433 1.186 1.247 indexOf(int) 1.31 1.327 -0.017 indexOfC8 2.042 0.857 1.185 charArrayEqual 0.826 0.446 0.38 s String.equals -0.001 0.002 -0.003
  • 39. おまけ (OpenJDK8)  OS 対応  BSD へ対応  CPU 依存部分  AVX へ対応  高速な macro を追加 fast_pow(), fast_exp()  FPInstruction を使って計算した log を元に pow と exp  C2 コンパイラ  OptimizePtrCompare オプションが追加。デフォルト true  EscapeAnalysis が大幅改良。 PtrCompare でごにょ  nest した lock/unlock の除去。 MemBarNode が増えたり