ジャストインタイムコンパイル方式
出典: フリー百科事典『ウィキペディア(Wikipedia)』
ジャストインタイムコンパイル(Just In Time Compilation、JITコンパイル、その都度のコンパイル)方式とは、ソフトウェアの実行時にコードのコンパイルを行い実行速度の向上を図る方式であり、 動的コンパイルとも呼ぶ。通常のコンパイラはソースコード(あるいは中間コード)から対象言語への変換を実行前に(コンパイル時に)行う。これをJITと対比して事前コンパイル (Ahead Of Time, AOT) コンパイルと呼ぶ。
事前コンパイル方式と比べ、JIT方式ではコンパイル時間の分がプログラム実行時間に関するオーバーヘッドとなる。また、事前コンパイルで可能な、高度で時間のかかる最適化を行うことは許されない。これは、実行速度を向上させるためにコンパイルするのだから、あまり時間がかかっては意味がないためである。
事前のコンパイルと比べてこのような不利な点を持ちながらも、JIT方式が有用なのは、実行時にコンパイルを行うことでオペレーティングシステムやCPUに依存しないソースコードや中間コードの状態でソフトウェアを配布することができるからである。
JITを装備した処理系は、表面上はインタプリタとして動作するが、内部でコンパイルを行い、メモリ上に生成した機械語コード(対象コード)が実行されるため、インタプリタと比べると実行速度を向上することができる。この意味で、JITはCPUやOSに依存しない実行形式を配布できる、というインタプリタの利点を保ったまま、実行速度が遅い、という欠点を克服しようとするものといえる。
目次 |
[編集] インタプリタ方式との比較
JITコンパイルをメソッドのロード時や、クラスのロード時に行う場合、プログラムの大幅な起動時間の低下がもたらされる。また、一般にコンパイル後のコードはコンパイル前のコードより抽象度が低く、コンパイル後のコードを保持するために必要なメモリ容量が大幅に増大する。
[編集] 適応的コンパイル (Adaptive Compilation)
上のようなJITコンパイラの短所を補うためのJITコンパイルの一方式として適応的コンパイルという方式がある。これは、起動当初はインタプリタとして実行し、よく呼び出されるメソッドや繰り返し実行されるコードの検出(プロファイリング)を行い、そのようなコードのみをコンパイルする、というものである。このとき、コードが使われた時にすぐにコンパイルするのではなく、何回か呼ばれた後に遅らせてコンパイル を行うが、このことを遅延コンパイル (Lazy Compilation)と呼ぶ。一般にプログラムの実行においてその実行時間の大半はプログラム中のごく一部において費やされる、という経験則がある(実際の比率については状況に依存するが、典型的にはコードの実行時間の80%は20%のコードにおいて費やされるといわれ、80-20の法則と呼ばれる)が、適応的コンパイルにおいては実行時間の大半が費やされるような、ボトルネックとなるコードのみをコンパイルすることで、起動時のオーバーヘッドや利用メモリ増大を抑えたうえで、効率よく実行速度を向上することができる。 この適応的コンパイルによる適応的最適化 (Adaptive Optimization) は、静的コンパイルでは得られない情報を元に最適化が行えるため、静的コンパイルより、むしろパフォーマンスが上がる場合もある。
[編集] JITコンパイル方式の利点
JITコンパイル方式と事前コンパイルの生成コードの質を比べると、前述のようにコンパイル時間に対する制約のためJIT方式の方が不利であるが、有利な点もある。それは、実行環境を知った上でそれに応じた生成コードの選択や最適化を行うことができるということである。
Intel社のx86CPUを例にとって見ると、IA32アーキテクチャの範囲内でもそれぞれの世代でさまざまに命令が拡張されてきているが、アプリケーションコードの後方互換性を保持する場合、実行バイナリ中では386と互換の命令しか使うことができない。 つまり、MMX PentiumのMMX命令を含んだコードは80386やPentiumでは実行できない。しかし、JIT方式では、CPUがMMXをサポートしているならMMX命令を使ったコードを生成し、 そうでなければ多少効率の悪いPentiumの命令の範囲内での実行を行う、ということができる。
また、実行環境におけるキャッシュやメモリのサイズ、速度特性なども実行時にならないと最終的にはわからない。JITコンパイル方式では実際に走行しているCPUやメモリの情報を知ることができるため、 それに応じたコードを生成することができ、事前コンパイルよりも優れたコードを生成できる可能性がある。
さらに、オブジェクト指向言語の実行においては仮想メソッドの呼び出しは仮想関数表を経由した間接呼び出しになるが、動的コンパイルにおいては、そのメソッドをオーバーライド定義したサブクラスが存在しない限り、 間接呼び出しを静的束縛として呼び出したり、あるいはインライン展開することができる(そのメソッドをオーバーライドするサブクラスが動的にロードされる可能性があるが、その場合はこのコンパイルされたメソッドは最適化戻し (deoptimize) される必要がある)。
[編集] 応用
JIT処理はJava技術の普及に伴い広範囲に使われるようになったが、JavaのHotspot技術はSunにおけるSelf言語での動的コンパイル技術研究に基づいており、それに先立つ商用Smalltalk処理系でもJITコンパイル技術は確立されていた。
JIT技術はトランスメタ社によるCrusoeでx86コードからCrusoeのVLIW命令への変換に用いられている。 適応的コンパイル技術はDEC社によるFX!32技術でも用いられていた。
Microsoft社による.NETプラットフォームも当初からJITによる実行を前提に設計されている。
[編集] JavaのJITコンパイラ
Symantec社によるsymjitおよびBorland社によるJITコンパイラは初期の主要なJITコンパイラであった。
Sun Microsystems自身によるHotSpotコンパイラは本格的に適応的コンパイル方式を採用したJIT処理系である。 Hotspot以降はJITコンパイラ部分のインターフェースが規定されており、 JITコンパイルエンジン部分を差し替えることができるようになった。
IBMによるIBM JDK、BEAによるJRockitはいずれも適応的コンパイルを行う独自のJIT処理系を持っている。後者は特にx86に特化して実行効率を高めている。
学術的なものとしては、首藤氏によるShuJITや、富士通研と東工大によるリフレクション機能を扱うOpenJITなどがある。