次の方法で共有


アプリケーションの起動時間

WPF アプリケーションの起動に必要な時間は、大きく異なる場合があります。 このトピックでは、Windows Presentation Foundation (WPF) アプリケーションで認識される実際の起動時間を短縮するためのさまざまな手法について説明します。

コールド スタートアップとウォーム スタートアップについて

コールド スタートアップは、システムの再起動後に初めてアプリケーションを起動したとき、またはアプリケーションを起動して閉じてから、長い時間が経過した後にもう一度起動したときに発生します。 アプリケーションの起動時に、必要なページ (コード、静的データ、レジストリなど) が Windows メモリ マネージャーのスタンバイ リストに存在しない場合、ページ エラーが発生します。 ページをメモリに取り込むには、ディスク アクセスが必要です。

ウォーム スタートアップは、メイン共通言語ランタイム (CLR) コンポーネントのほとんどのページが既にメモリに読み込まれている場合に発生します。これにより、コストのかかるディスク アクセス時間が節約されます。 そのため、マネージド アプリケーションは 2 回目の実行時に起動が速くなります。

スプラッシュ スクリーンを実装する

アプリケーションの起動から最初の UI の表示までの間に、避けられない重大な遅延がある場合は、 スプラッシュスクリーンを使用して、認識される起動時間を最適化します。 この方法では、ユーザーがアプリケーションを起動した直後に画像が表示されます。 アプリケーションが最初の UI を表示する準備ができたら、スプラッシュ画面がフェードします。 .NET Framework 3.5 SP1 以降では、 SplashScreen クラスを使用してスプラッシュスクリーンを実装できます。 詳細については、「 WPF アプリケーションにスプラッシュスクリーンを追加する」を参照してください。

ネイティブ Win32 グラフィックスを使用して、独自のスプラッシュスクリーンを実装することもできます。 Run メソッドが呼び出される前に実装を表示します。

スタートアップ コードの分析

コールドスタートアップが遅くなる原因を特定する。 ディスク I/O が原因である可能性がありますが、必ずしもそうであるとは限りません。 一般に、ネットワーク、Web サービス、ディスクなどの外部リソースの使用を最小限に抑える必要があります。

テストする前に、実行中の他のアプリケーションまたはサービスでマネージド コードまたは WPF コードが使用されていないことを確認します。

再起動の直後に WPF アプリケーションを起動し、表示にかかる時間を決定します。 アプリケーションのそれ以降のすべての起動 (ウォーム スタートアップ) がはるかに高速な場合、コールド スタートアップの問題は、I/O が原因である可能性が最も高くなります。

アプリケーションのコールド スタートアップの問題が I/O に関連していない場合は、アプリケーションが長い初期化または計算を実行したり、イベントが完了するのを待機したり、起動時に多くの JIT コンパイルを必要としたりする可能性があります。 以下のセクションでは、これらの状況の一部について詳しく説明します。

モジュールの読み込みを最適化する

プロセス エクスプローラー (Procexp.exe) や Tlist.exe などのツールを使用して、アプリケーションが読み込むモジュールを決定します。 コマンド Tlist <pid> には、プロセスによって読み込まれるすべてのモジュールが表示されます。

たとえば、Web に接続していない場合、System.Web.dll が読み込まれていることがわかります。アプリケーションには、このアセンブリを参照するモジュールがあります。 参照が必要であることを確認します。

アプリケーションに複数のモジュールがある場合は、それらを 1 つのモジュールにマージします。 この方法では、CLR アセンブリの読み込みオーバーヘッドが少なくなります。 アセンブリの数が少ないほど、CLR の状態の維持も少なくなります。

初期化操作を延期する

メイン アプリケーション ウィンドウがレンダリングされるまで初期化コードを延期することを検討してください。

初期化はクラス コンストラクター内で実行される可能性があり、初期化コードが他のクラスを参照している場合は、多くのクラス コンストラクターが実行される連鎖的な影響を引き起こす可能性があることに注意してください。

アプリケーション構成の回避

アプリケーションの構成を回避することを検討してください。 たとえば、アプリケーションに単純な構成要件があり、厳密な起動時間の目標がある場合、レジストリ エントリまたは単純な INI ファイルを使用すると、より高速な起動の代替になる場合があります。

GAC を利用する

アセンブリがグローバル アセンブリ キャッシュ (GAC) にインストールされていない場合、厳密な名前付きアセンブリのハッシュ検証と、そのアセンブリのネイティブ イメージがコンピューターで使用可能な場合は Ngen イメージ検証によって遅延が発生します。 GAC にインストールされているすべてのアセンブリについて、厳密な名前の検証はスキップされます。 詳細については、「Gacutil.exe (グローバル アセンブリ キャッシュ ツール)」を参照してください。

Ngen.exe を使用する

アプリケーションでネイティブ イメージ ジェネレーター (Ngen.exe) を使用することを検討してください。 Ngen.exe を使用すると、Ngen.exe によって生成されるネイティブ イメージが MSIL イメージよりも大きくなる可能性があるため、より多くのディスク アクセスのために CPU 消費量を取引することを意味します。

ウォーム スタートアップ時間を短縮するには、アプリケーション コードの JIT コンパイルの CPU コストを回避するため、常にアプリケーションで Ngen.exe を使用する必要があります。

一部のコールド スタートアップ シナリオでは、Ngen.exe の使用も役立ちます。 これは、JIT コンパイラ (mscorjit.dll) を読み込む必要がないためです。

Ngen モジュールと JIT モジュールの両方を持つことは、最悪の影響を及ぼす可能性があります。 これは、mscorjit.dll を読み込む必要があり、JIT コンパイラがコードで動作する場合、JIT コンパイラがアセンブリのメタデータを読み取るときに Ngen イメージ内の多くのページにアクセスする必要があるためです。

Ngen と ClickOnce

アプリケーションのデプロイを計画する方法によって、読み込み時間も異なる場合があります。 ClickOnce アプリケーションの配置では、Ngen はサポートされていません。 アプリケーションに Ngen.exe を使用する場合は、Windows インストーラーなどの別の展開メカニズムを使用する必要があります。

詳細については、「Ngen.exe (ネイティブ イメージ ジェネレーター)」を参照してください。

リベースと DLL アドレスの衝突

Ngen.exeを使用する場合は、ネイティブ イメージがメモリに読み込まれるときに再調整が発生する可能性があることに注意してください。 そのアドレス範囲が既に割り当てられているため、DLL が優先ベース アドレスで読み込まれていない場合、Windows ローダーは別のアドレスで DLL を読み込みます。これは、時間のかかる操作になる可能性があります。

仮想アドレス ダンプ (Vadump.exe) ツールを使用して、すべてのページがプライベートなモジュールがあるかどうかを確認できます。 この場合、モジュールが別のアドレスにリベースされている可能性があります。 そのため、そのページを共有することはできません。

ベース アドレスを設定する方法の詳細については、「 Ngen.exe (ネイティブ イメージ ジェネレーター)」を参照してください。

Authenticode を最適化する

Authenticode 検証が起動時間に追加されます。 Authenticode 署名付きアセンブリは、証明機関 (CA) で検証する必要があります。 現在の証明書失効リストをダウンロードするためにネットワークに複数回接続する必要があるため、この検証には時間がかかる場合があります。 また、信頼されたルートへのパスに有効な証明書の完全なチェーンがあることも確認します。 これにより、アセンブリの読み込み中に数秒の遅延が発生する可能性があります。

クライアント コンピューターに CA 証明書をインストールすることを検討するか、可能な場合は Authenticode の使用を避けてください。 アプリケーションに発行元の証拠が必要ないことがわかっている場合は、署名検証のコストを支払う必要はありません。

.NET Framework 3.5 以降では、Authenticode 検証をバイパスできるようにする構成オプションがあります。 これを行うには、app.exe.config ファイルに次の設定を追加します。

<configuration>
    <runtime>
        <generatePublisherEvidence enabled="false"/>
    </runtime>
</configuration>

詳細については、「 <generatePublisherEvidence> 要素」を参照してください。

Windows Vista でのパフォーマンスの比較

Windows Vista のメモリ マネージャーには、SuperFetch と呼ばれるテクノロジがあります。 SuperFetch は、時間の経過に伴うメモリ使用量パターンを分析して、特定のユーザーに最適なメモリ コンテンツを決定します。 常にそのコンテンツを維持するために継続的に機能します。

この方法は、使用パターンを分析せずにデータをメモリにプリロードする Windows XP で使用されるプリフェッチ手法とは異なります。 時間の経過と同時に、ユーザーが Windows Vista で WPF アプリケーションを頻繁に使用する場合、アプリケーションのコールド スタートアップ時間が長くなる可能性があります。

AppDomains を効率的に使用する

可能であれば、アセンブリをドメインに依存しないコード領域に読み込み、ネイティブ イメージが存在する場合は、アプリケーションで作成されたすべての AppDomain で使用されるようにします。

最適なパフォーマンスを得るため、クロスドメイン呼び出しを減らすことで、効率的なクロスドメイン通信を強制します。 可能な場合は、引数を指定せずに、またはプリミティブ型引数を使用して呼び出しを使用します。

NeutralResourcesLanguage 属性を使用する

NeutralResourcesLanguageAttributeを使用して、ResourceManagerのニュートラル カルチャを指定します。 この方法では、アセンブリ参照の失敗を回避できます。

XML シリアライザー ジェネレーターを使用する

XmlSerializer クラスを使用する場合は、XML シリアライザー ジェネレーター ツール (Sgen.exe) を使用してシリアル化アセンブリを事前生成すると、パフォーマンスが向上します。

起動時に更新プログラムをチェックするように ClickOnce を構成する

アプリケーションで ClickOnce を使用している場合は、アプリケーションの起動後に配置サイトで更新プログラムを確認するように ClickOnce を構成することで、起動時にネットワーク アクセスを回避します。

XAML ブラウザー アプリケーション (XBAP) モデルを使用する場合は、XBAP が既に ClickOnce キャッシュ内にある場合でも、ClickOnce は配置サイトで更新プログラムをチェックします。 詳細については、「 ClickOnce のセキュリティと配置」を参照してください。

警告

XBAP では、Internet Explorer や古いバージョンの Firefox など、従来のブラウザーが動作する必要があります。 これらの古いブラウザーは、通常、Windows 10 および Windows 11 ではサポートされていません。 最新のブラウザーでは、セキュリティ リスクのために XBAP アプリに必要なテクノロジがサポートされなくなりました。 XBAP を有効にするプラグインはサポートされなくなりました。 詳細については、「WPF ブラウザーでホストされるアプリケーション (XBAP)についてよく寄せられる質問を参照してください。

PresentationFontCache サービスを自動的に開始するように構成する

再起動後に実行する最初の WPF アプリケーションは PresentationFontCache サービスです。 このサービスは、システム フォントをキャッシュし、フォント アクセスを向上させ、全体的なパフォーマンスを向上させます。 サービスの開始にはオーバーヘッドがあり、一部の制御された環境では、システムの再起動時に自動的に開始するようにサービスを構成することを検討してください。

プログラムによるデータ バインディングの設定

XAML を使用してメイン ウィンドウの DataContext を宣言的に設定する代わりに、 OnActivated メソッドでプログラムによって設定することを検討してください。

こちらも参照ください