ネイティブ イメージ
単純な形式のネイティブ コードの生成は、メソッドを初めて実行する直前に、Jst-In-Time (JIT) コンパイラが Microsoft Intermediate Language (MSIL) コードをアセンブリからローカル コンピューター用のネイティブ コードにコンパイルするときに発生します。 このネイティブ コードは一時的なもので、実行中のプロセスのメモリ空間に格納され、プロセスの終了時にオペレーティング システムによって再利用されます。 したがって、ネイティブ コードは新しいプロセスがそれを必要とするたびに再生成されます。
一方で、ネイティブ イメージ ジェネレーター (Ngen.exe) はアセンブリを読み込み、JIT コンパイラを呼び出して、アセンブリ全体をネイティブ コードにコンパイルします。 その結果得られるネイティブ イメージは、真の Win32 の移植性の高い実行可能 (PE: Portable Executable) ファイルになり、ネイティブ イメージ キャッシュと呼ばれるハード ディスクの場所に格納されます。 アプリケーションがアセンブリを必要とした場合、共通言語ランタイム (CLR) は元のアセンブリと JIT コンパイラの代わりにネイティブ イメージを読み込みます。 CLR はネイティブ イメージを持っているアセンブリに関する情報と、イメージがデバッグの目的に作成されたかどうかなどの追加情報を維持します。
ネイティブ イメージの利点
ネイティブ イメージによって、メモリ使用の改善と起動時間の短縮の 2 つの領域においてパフォーマンスが向上します。
メモリ使用の改善
プロセス間でコードを共有する場合は、ネイティブ イメージによってメモリ使用を大いに改善できます。 ネイティブ イメージは Windows PE ファイルであるため、1 つのコピーを複数のプロセスで共有できます。 一方、JIT コンパイラが生成するネイティブ コードはプライベート メモリに格納されるため、共有できません。
ターミナル サーバーで実行されるアプリケーションも、共有されたコード ページの恩恵を受けることができます。
JIT コンパイラを読み込まないため、各アプリケーション インスタンスが使用する固定メモリの量も減らすことができます。
アプリケーションの起動の高速化
Ngen.exe によってアセンブリをプリコンパイルすることにより、一部のアプリケーションの起動時間が短縮されます。 一般に、最初のアプリケーションが起動されると、その後のアプリケーションが使用する共有コンポーネントが読み込まれるため、アプリケーションがコンポーネント アセンブリを共有している場合にアプリケーションの起動時間が短縮されます。 アプリケーションのすべてのアセンブリをハード ディスクから読み込む必要があるコールド スタートでは、ハード ディスクのアクセス時間の影響の方が大きいため、ネイティブ イメージから受け取る恩恵はそれほど大きくありません。
メイン アプリケーション アセンブリにハード バインディングされているすべてのイメージは同時に読み込む必要があるため、ハード バインディングは起動時間に影響します。
ネイティブ イメージに関する考慮事項
アプリケーションがネイティブ イメージの自動生成をサポートしているシナリオで実行されない場合 (これらのシナリオの詳細については「ネイティブ イメージの作成」を参照) は、アプリケーション用のネイティブ イメージを手動で生成するかどうかを判断するにあたって以下の考慮事項が役に立ちます。
ネイティブ イメージでは、JIT コンパイル、タイプ セーフ検証などの多くの起動時アクティビティが不要なため、MSIL より読み込みが高速になります。
ネイティブ イメージでは JIT コンパイラが不要なため、必要な初期作業セットが少なくてすみます。
ネイティブ イメージによって、プロセス間でコードを共有できます。
ネイティブ イメージは MSIL アセンブリよりも多くのハード ディスク容量を必要とし、生成にかなりの時間を要する場合があります。
ネイティブ イメージは保持する必要があります。
元のアセンブリまたはその依存関係のいずれかに対してサービスを提供する場合は、イメージを再生成する必要があります。
アプリケーションまたはシナリオごとに異なるネイティブ イメージを使用する場合、1 つのアセンブリで複数のネイティブ イメージが必要な場合があります。 たとえば、2 つのアプリケーションの構成情報で、同じ依存アセンブリに対してバインディング決定が異なる場合です。
ネイティブ イメージは管理者が作成する必要があります。つまり Administrators グループの Windows アカウントから作成します。
このような一般的な考慮事項に加えて、ネイティブ イメージによってパフォーマンスが向上するかどうかを判断する場合は、アプリケーションの特性も考慮する必要があります。
多くの共有コンポーネントを使用する環境でアプリケーションを実行する場合は、ネイティブ イメージによってコンポーネントを複数のプロセスで共有できます。
アプリケーションが複数のアプリケーション ドメインを使用する場合は、ネイティブ イメージによってドメイン間でコード ページを共有できます。
アプリケーションをターミナル サーバーで実行する場合は、ネイティブ イメージによってコード ページを共有できます。
サイズの大きなアプリケーションでは、一般にネイティブ イメージにコンパイルすることでパフォーマンスが向上します。 サイズの小さなアプリケーションでは、一般にあまり有効ではありません。
長時間実行するアプリケーションでは、ランタイム JIT コンパイルのパフォーマンスの方がネイティブ イメージよりも若干優れています。ハード バインディングによって、このパフォーマンスの違いをある程度緩和できます。