Edited at

Unity開発するにあたって知っておきたいコンパイラのすゝめ(Part0.7~JITとAOT概要編~)


最初に

この記事はUnityで使用されているコンパイラについてまとめた記事のうちの、土台部分であるJITAOTについて簡単にまとめた記事です。そのため、Part1ではなく、とっかかりという意味で0.7と記載させて頂きました。


JITって何?

前回.NET Frameworkの概要を解説した際に、VES(仮想実行環境)でマシン語をJITで実行すると書きました。

JITとはJust-In-Timeの略称で、「実行時コンパイラ」とも呼ばれています。ニュアンスとしては「ちょうどよい時に」となります。

このJITコンパイル方式では、コードの中で実際に実行されるILコード部分が都度都度マシン語に翻訳され、メモリの実行領域にvtableとネイティブコードが生成され、実行されます。逆にいえば、初期状態のメモリの実行領域には、フレームワーク側のコードだけしか読み込まれていません。

image.png

クラスA初回読み込み時にクラスAに関するvtable(①)を作成します。次にHogeが初めて呼ばれた場合はHogeのネイティブコード化(②)を行い、クラスAのvtableにHogeのネイティブコードを指すメモリアドレスを格納します。こうして、2回目以降は直接Hogeのネイティブコードを呼び出すため、初回以降は高速に実行が可能です。

このJITコンパイルによって、プラットフォームに依存しないILコードのまま.NET製のプログラムやライブラリ等を配布することが可能です。


AOTって何?

AOTコンパイラとはAhead-Of-Timeの略称で、「事前コンパイラ」とも呼ばれています。Jソースコードから中間コードを生成した後にネイティブの機械語も一緒に生成します。

C/C++ではAOTが主流で、これらの言語でコンパイラと言った時はAOTコンパイラのことを指すことが多いです。


JITとAOTのメリットデメリット


  • JITコンパイラが部分的な最適化だけを行うのに対し、AOTコンパイラは生成されたネイティブコードをプロセッサに合わせて全体の最適化が可能なので、異なるプロセッサごとに複数のコードを作成する必要がありません。そのためパフォーマンス面では基本的にAOTコンパイラが勝ります。ただしJITならば実際にそのコードを実行しているPCのCPUやメモリの情報を知ることができるので、それに応じたコードを生成したり最適化することができルため、AOTよりも優れたコードを生成できる可能性があります。


  • JITコンパイルの場合は最適化を行わないため非常に多くのメモリを消費します。できるだけアプリ自体のサイズを小さくしたいようなスマホ向けのアプリにはAOTコンパイルが相性が良いでしょう。


  • JITの性質上、ILをネイティブコード化する初回のタイミングで遅くなります(C#であればJITの中でも高速な部類です)。


  • ただ前述した通り、JITコンパイラではILコードをネイティブコードに翻訳しているので、プラットフォームに依存せず配布することが可能です。


  • JITの方がリフレクションなどの動的な処理を容易に扱いやすいです。ただしリフレクション自体実行速度が落ちがちなので基本的には避けますが…。


  • さらに、JITはセキュリティが担保しやすいため、ストア審査が通りやすいです。



最後に

JITとAOTの基礎的な概念は理解できていてもメリット・デメリットまでは確認していなかったため、今回調べてみたことで良い勉強になりました。


参考