以下はネイティブコンパイルとJITコンパイルの違いを比較するだけであり、特定の言語またはフレームワークの詳細はカバーしないことに注意してください。これを超えて特定のプラットフォームを選択する正当な理由があるかもしれません。
ネイティブコードの方が速いと主張するとき、ネイティブコンパイルされたコードとJITコンパイルされたコードの典型的なユースケースについて話します。最初にコンパイラを待機します)。その場合、JITでコンパイルされたコードはネイティブコードに匹敵する、または打ち負かすことができると、誰もがまっすぐに主張することはできないと思います。
ある言語Xで書かれたプログラムがあり、ネイティブコンパイラでコンパイルでき、再びJITコンパイラでコンパイルできると仮定しましょう。各ワークフローには、(コード->中間表現->マシンコード->実行)として一般化できる同じステージが含まれます。2つの大きな違いは、ユーザーが見るステージとプログラマーが見るステージです。ネイティブコンパイルでは、プログラマは実行ステージ以外のすべてを見ることができますが、JITソリューションでは、実行に加えて、マシンコードへのコンパイルがユーザーに表示されます。
AがBより速いという主張は、ユーザーに見えるように、プログラムの実行にかかる時間を指します。実行段階で両方のコードが同じように動作すると仮定する場合、マシンコードへのコンパイルの時間T(T> 0)も確認する必要があるため、JITワークフローはユーザーにとって遅いと仮定する必要があります。 、JITワークフローがネイティブワークフローと同じように実行される可能性がある場合、ユーザーはコードの実行時間を短縮し、実行+マシンコードへのコンパイルが実行ステージよりも短くなるようにする必要がありますネイティブのワークフローの。つまり、ネイティブコンパイルよりもJITコンパイルの方がコードを最適化する必要があります。
ただし、これはかなり実行不可能です。実行を高速化するために必要な最適化を実行するには、マシンコードステージへのコンパイルにより多くの時間を費やさなければならず、したがって、コンパイルに追加します。言い換えれば、JITベースのソリューションの「遅さ」は、単にJITコンパイルに時間を追加しただけでなく、そのコンパイルによって生成されたコードのパフォーマンスがネイティブソリューションよりも遅いためです。
例を使用します:レジスターの割り当て。メモリアクセスはレジスタアクセスよりも数千倍遅いため、可能な限りレジスタを使用し、できるだけ少ないメモリアクセスを行うことが理想ですが、レジスタの数は限られているため、必要なときに状態をメモリにスピルする必要がありますレジスタ。計算に200ミリ秒かかるレジスタ割り当てアルゴリズムを使用し、その結果、実行時間を2ミリ秒節約した場合、JITコンパイラの時間を最大限に活用できません。高度に最適化されたコードを生成できるChaitinのアルゴリズムのようなソリューションは不適切です。
JITコンパイラーの役割は、コンパイル時間と生成コードの品質の最適なバランスをとることです。ただし、ユーザーを待たせたくないので、高速コンパイル時間に大きな偏りがあります。JITの場合、実行されるコードのパフォーマンスは遅くなります。これは、ネイティブコンパイラがコードを最適化する際に時間に拘束されないため、最適なアルゴリズムを自由に使用できるためです。JITコンパイラの全体的なコンパイルと実行が、ネイティブにコンパイルされたコードの実行時間のみに勝る可能性は事実上0です。
ただし、VMは単にJITコンパイルに限定されているわけではありません。それらは、事前コンパイル技術、キャッシュ、ホットスワッピング、および適応最適化を採用しています。そのため、パフォーマンスはユーザーが見るものであるという主張を修正し、プログラムの実行にかかる時間に制限しましょう(AOTをコンパイルしたと仮定します)。実行中のコードをネイティブコンパイラと同等の効果的なものにすることができます(または、おそらくもっと良いのでしょうか?)。VMの大きな主張は、特定の機能が実行される頻度など、実行中のプロセスの情報にアクセスできるため、ネイティブコンパイラよりも高品質のコードを生成できる可能性があることです。VMは、ホットスワップを介して最も重要なコードに適応最適化を適用できます。
ただし、この引数には問題があります。プロファイルに基づく最適化などがVMに固有のものであると想定されていますが、これは正しくありません。プロファイリングを有効にしてアプリケーションをコンパイルし、情報を記録し、そのプロファイルでアプリケーションを再コンパイルすることにより、ネイティブコンパイルにも適用できます。また、コードのホットスワッピングはJITコンパイラーだけができることではなく、ネイティブコードに対してもできることを指摘する価値があります。ただし、これを行うためのJITベースのソリューションはより簡単に入手でき、開発者にとってはるかに簡単です。大きな問題は、VMがネイティブコンパイルでは得られない情報を提供して、コードのパフォーマンスを向上できるかどうかということです。
自分で見ることができません。プロセスはより複雑ですが、典型的なVMの技術のほとんどをネイティブコードにも適用できます。同様に、AOTコンパイルまたは適応最適化を使用するVMにネイティブコンパイラの最適化を適用できます。現実には、ネイティブに実行されるコードとVMで実行されるコードの違いは、私たちが信じさせられたほど大きくありません。最終的には同じ結果につながりますが、そこに到達するために異なるアプローチを取ります。VMは反復アプローチを使用して最適化されたコードを生成します。ネイティブコンパイラは最初からそれを想定しています(反復アプローチで改善できます)。
C ++プログラマーは、get-goからの最適化が必要だと主張するかもしれません。VMがそれらを行う方法を見つけ出すのを待っているべきではありません。VMの最適化の現在のレベルはネイティブコンパイラが提供できるものよりも劣るので、これはおそらく現在のテクノロジの有効なポイントです。