.NET 言語はすべて中間言語 ( MSIL ) にコンパイルされます。
私の知る限り、実行中 (および、NGEN について十分に理解していない他の段階の場合もあります)、コードは JITted ( MSILから実際のマシン コードにコンパイル) されています。
コードを JIT した後、コードが CLR で実行されているという事実に起因するパフォーマンスの「ペナルティ」があるのか 、それともコードが他のネイティブコードと「同じ」ように動作するのか疑問に思っていますか?
いくつかのパフォーマンスの違いがあります。
管理対象オブジェクトのフリー ストアは、ヒープではなくスタックとして実装され (Large Object Heap を除く)、ほとんどのネイティブ アロケーターで使用されるヒープよりもオーバーヘッドが低くなります。ただし、ガベージ コレクションと圧縮の料金は後で支払う必要があります。
JIT は、AOT コンパイラが仮想のままにしなければならない一部の呼び出し (つまり、他のアセンブリへの呼び出し) をインライン化できます。しかし、AOT コンパイラーは、最適化の機会を探すために、より多くの時間を費やすことができます。
理論的には、JIT は、コードを実行している特定の CPU (AVX など) に存在する高度な命令を使用できます。ただし、実際にそれらを有効に活用する JIT をまだ待っています。
AOT コンパイラは、プロファイリング データを使用して、コード メモリのレイアウトを制御できます。JIT コンパイラは、ほとんどの場合、コンパイルされた順序で関数をメモリに出力します。
JIT されたコードの主なパフォーマンス ペナルティは、最初の実行時にコードをコンパイルするのにかかる時間です。これは通常、起動時間が (わずかに、おそらく気付かない程度に) 長くなるだけですが、すべての要求を処理するために新しいプロセスが生成される CGI のようなシナリオで使用している場合は、実際にヒットする可能性があります。.NET で記述された CGI スクリプトが一般的なユース ケースであるというわけではありませんが、頭に浮かんだ最初の例なので、それを使用して実行します。
NGen は、JIT ステップをスキップすることで起動時間を改善できます。このメリットは、CGI スクリプトのように頻繁に実行される短時間のプログラムで最大になります。(または、おそらく、自動的に開始するように設定された Windows サービスがより良い例だと思います。) 頻繁に実行されないプログラムの場合、実行可能ファイルはメモリにキャッシュされる可能性が低いため、おそらく実行ファイルからロードする必要があります。毎回ディスク。ディスクからの読み取りにかかる時間が起動時間を支配し、NGen のメリットを圧倒する可能性があります。また、長時間実行されるプログラムの場合、起動時間はおそらく重要なパフォーマンス特性ではありません。
通常、ネイティブに記述されたコードは、設計時に知る必要がある特定のアーキテクチャ (SSE など) で利用できる最適化を使用できるため、パフォーマンスが向上します。ガベージ コレクションと手動メモリ管理など、言語のパフォーマンスについて考慮すべき点が他にもあります。
NGENに関する限り、実行時にJITTEDコードが生成されることを除いて、JITTEDコードとNGENが行うこととの間にパフォーマンスの違いはあまりないと思います(実際のコンパイルが発生するとパフォーマンスが低下します)。