15

起動直後にアプリケーションが適切に動作するように、アプリケーションを最適化しようとしています。現在、そのディストリビューションには 304 個のバイナリ (外部依存関係を含む) が含まれており、合計で 57 メガバイトになります。これは、重要な計算を行わずに、主にデータベース アクセスを行う WPF アプリケーションです。

ほとんどの操作は、アプリケーションのプロセスの存続期間中に初めて実行されるため、Debug 構成の方がはるかに優れた (最大 5 倍のゲイン) 時間を提供することがわかりました。たとえば、アプリ内で特定の画面を開くには、NGENed Debug で 0.3 秒、JITted Debug で 0.5 秒、NGENed Release で 1.5 秒、JITted Release で 2.5 秒かかります。

JIT コンパイル時間のギャップは、リリース バイナリに対してより積極的な最適化を適用する JIT コンパイラによって引き起こされることを理解しています。私が知る限り、デバッグ構成とリリース構成は、C# コンパイラに渡される/p:DebugTypeおよびスイッチによって異なりますが、アプリケーションをビルドした場合でも、同じパフォーマンス ギャップが見られます。つまり、 と同じイメージ デバッグ オプションです。/p:Optimize/p:Configuration=Release /p:DebugType=full /p:Optimize=false/p:Configuration=Debug

DebuggableAttribute結果のアセンブリに適用された を見て、オプションが適用されたことを確認します。NGEN の出力を観察すると、<debug>コンパイルされているいくつかのアセンブリの名前に追加されていることがわかります。NGEN はデバッグ アセンブリと非デバッグ アセンブリをどのように区別しますか? テスト対象の操作は動的コード生成を使用しています。動的コードにはどのレベルの最適化が適用されていますか?

注: 外部依存関係のため、32 ビット フレームワークを使用しています。x64 では異なる結果が期待できますか?

注: 条件付きコンパイルも使用しません。したがって、コンパイルされたソースは両方の構成で同じです。

4

3 に答える 3

2

あなたが言うように、304 個のアセンブリをロードする必要がある場合、これがアプリの実行速度が遅い原因である可能性があります。これは、ロードするアセンブリの数が非常に多いようです。

CLR は、AppDomain にまだ読み込まれていない別のアセンブリからコードに到達するたびに、それをディスクから読み込む必要があります。

ILMerge を使用して、これらのアセンブリの一部をマージすることを検討してください。これにより、アセンブリをディスクからロードする際の遅延が短縮されます (1 つの大きなディスク ヒットを前もって処理します)。

すべてがマージされるのが好きというわけではないので、多少の実験が必要になる場合があります (特に、Reflection を使用し、変更されないアセンブリ ファイル名に依存するもの)。また、アセンブリが非常に大きくなる場合もあります。

于 2012-05-07T05:13:09.347 に答える
1

デバッガー ('F5') で実行していますか、それともデバッガーなし ('ctrl+F5') で実行していますか? 前者の場合は、[ツール] -> [オプション] -> [デバッグ] -> [モジュールのロード時に JIT 最適化を抑制する] がオフになっていることを確認してください。

于 2012-05-06T20:23:46.717 に答える
1

さて、ここでいくつか質問します。

私が知る限り、デバッグ構成とリリース構成は、C# コンパイラに渡される /p:DebugType および /p:Optimize スイッチによって異なりますが、/p:Configuration=Release / を使用してアプリケーションをビルドしても、同じパフォーマンス ギャップが見られます。 p:DebugType=full /p:Optimize=false – つまり、/p:Configuration=Debug と同じイメージ デバッグ オプションです。

チェック ボックスは同じですが、リリース モードに変更すると、特定の内部コード パスも削除されますDebug.Assert()(Microsoft 内部コードで頻繁に使用されます)。したがって、これらは実行時に評価されないため、パフォーマンスがいくらか向上します。DebugType=fullコンパイルされたコードに一致する PDB を生成するため、それ自体はパフォーマンスに影響しません。PDB がデプロイされている場合、例外処理コードは PDB を使用して、コンパイルされたコードに対してより有用なスタック トレースを提供します。デバッグ バージョンはデバッガーのアタッチに使用されるため、リリース モードも内部的にメモリの改善をトリガーします。

NGEN は、アプリケーションを「潜在的に」最適化するために使用されるツールです。使用しているコンピューターに固有のコードが動作するように最適化します。ただし、JIT コンパイラはメモリ内のコードのレイアウトを変更できるのに対し、NGEN はその性質上より静的であるため、欠点がある可能性があります。

32 ビット (x86) の依存関係に関しては、アプリは x86 モードで実行されるようになります。依存関係に x86 と x64 の両方のバージョンがあり、アプリが「任意の CPU」コンパイル モードでコンパイルされている場合、JIT コンパイラは自動的に 2.NGEN を切り替えます。NGEN は、現在のコンピューターの特定のバージョンのみを生成します。したがって、NGEN を実行してから配布すると、コンパイルした特定のアーキテクチャに対してのみ機能します。

条件付きコンパイル機能を利用していない場合は、Debug から Release に切り替えても問題ありません。ただし、Release ではパフォーマンス上の利点が見られます。

NGEN では、広範囲にテストして 2 よりも優れていることを確認することをお勧めします。常にパフォーマンスが向上するとは限りません。

于 2012-04-21T11:49:01.207 に答える