1 つの最適化の例を挙げることができます。どこかに関数があるとします。(これを C ライクな疑似コードと考えてください。)
void function(MyClass x)
{
x.doSomething();
for (obj in x.getWidgets())
obj.doSomethingElse();
}
これは適切にあいまいです。ただし、イメージ全体で : を継承する具象クラスが 1 つしかないとしMyClass
ますMyConcreteClass
。その場合、JIT はインラインdoSomething
化できgetWidgets
ます。から返された型がわかっている場合はgetWidgets
、インライン化することもできdoSomethingElse
ます。
ここでそれが final/sealed クラスでないと仮定するとMyClass
、事前コンパイラーはそのメソッドをインライン化できません (どの関数をインライン化するかはわかりません)。コンパイラが知っている限りでは、 には 100 の異なる実装がありMyClass
ます。
ただし、JITはイメージの現在の状態を最適化できます。 への各呼び出しの最初に、それが であることを確認するチェックをインストールしてから、function
インラインバージョンを実行できます。から継承する別の具象クラスを使用してモジュールを動的にロードすると、チェックが失敗し、JIT は関数をジェネリックに再コンパイルします。x
MyConcreteClass
MyClass
これらは、JIT コンパイラーで使用できる唯一の種類の最適化であり、事前コンパイラーでは使用できません。プログラムの動的状態に関する情報を利用し、それに応じてプログラムを再コンパイルする最適化です。
一部の事前コンパイラーは、通常 JIT コンパイラーに起因するトリックを実行できることに注意してください。たとえば、手続き間の最適化 (またはグローバル最適化) やプロファイル主導の最適化などです。GCC と Clang はこれらのトリックの両方を使用できますが、それらをオンにするには余分な (人的) 作業が必要になるため、ほとんどの人はそれらをオフにします。JIT コンパイラは、エンド ユーザーを煩わせることなく、これらのオプションを有効のままにしておくことができます。
大幅なパフォーマンスの向上:一般的に、JIT コンパイラによってパフォーマンスが大幅に向上したという話は聞いたことがありません。C および C++ プログラムは、JIT がなくても高速です。そして、多くの人は今でも数値計算に Fortran を好んでいます (正当な理由があります)。
脚注:あなたの用語についてはよくわかりません。ほとんどの JIT はネイティブ コード コンパイラでもありませんか? JIT 以外の他のタイプのコンパイラーは、「事前」または AOT、またはおそらく「静的」と呼びます。(そして、「コンパイル済み」と「解釈済み」の間に信じられないほどあいまいな境界線があります。)