8

JITコンパイラがネイティブコードコンパイラでは不可能な最適化を行う方法と、これらの最適化によってパフォーマンスが大幅に向上する方法について、多くのことを読んだり聞いたりしました。

だから私は疑問に思っていました、たとえば、ネイティブコンパイラが実行できない.NET FrameworkまたはJVMが実行する最も重要な最適化は何ですか?また、これらはどのようにしてパフォーマンスを大幅に向上させますか?

この質問を正しく表現したかどうかはわかりませんが、コメントで説明することがたくさんあるかもしれません。

4

2 に答える 2

4

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 は関数をジェネリックに再コンパイルします。xMyConcreteClassMyClass

これらは、JIT コンパイラーで使用できる唯一の種類の最適化であり、事前コンパイラーでは使用できません。プログラムの動的状態に関する情報を利用し、それに応じてプログラムを再コンパイルする最適化です。

一部の事前コンパイラーは、通常 JIT コンパイラーに起因するトリックを実行できることに注意してください。たとえば、手続き間の最適化 (またはグローバル最適化) やプロファイル主導の最適化などです。GCC と Clang はこれらのトリックの両方を使用できますが、それらをオンにするには余分な (人的) 作業が必要になるため、ほとんどの人はそれらをオフにします。JIT コンパイラは、エンド ユーザーを煩わせることなく、これらのオプションを有効のままにしておくことができます。

大幅なパフォーマンスの向上:一般的に、JIT コンパイラによってパフォーマンスが大幅に向上したという話は聞いたことがありません。C および C++ プログラムは、JIT がなくても高速です。そして、多くの人は今でも数値計算に Fortran を好んでいます (正当な理由があります)。

脚注:あなたの用語についてはよくわかりません。ほとんどの JIT はネイティブ コード コンパイラでもありませんか? JIT 以外の他のタイプのコンパイラーは、「事前」または AOT、またはおそらく「静的」と呼びます。(そして、「コンパイル済み」と「解釈済み」の間に信じられないほどあいまいな境界線があります。)

于 2012-04-13T08:22:11.740 に答える
1

Javascript は、JVM や CLR ほどコンパイラーに優しくないため、より良い例です。

JIT コンパイラーは、プログラム実行中の任意の時点でクラスを変更できるため、静的コンパイラーにとっては困難な Javascript クラスの具体的な特殊表現を生成できます。実際の型に基づいて、呼び出された関数を投機的にインライン化することもできます (Dietrich Epp は、彼の回答で既に説明しています)。

http://code.google.com/p/v8/のビデオでは、これらの最適化についてうまく説明されています。

于 2012-04-13T10:27:28.617 に答える