2012-04-16 9 views
14

私はアプリケーションを起動した直後にうまく機能するようにアプリケーションを最適化しようとしています。現時点では、その配布には、合計57メガバイトの304バイナリ(外部依存関係を含む)が含まれています。 WPFアプリケーションは、大部分の計算をすることなく、主にデータベースアクセスを行います。.NET JITコンパイルのパフォーマンス(動的メソッドを含む)は、C#コンパイラのイメージデバッグオプションの影響を受けますか?

私は、デバッグ設定が、アプリケーションのプロセスの存続期間中に初めて実行されるため、ほとんどの操作でより良い(〜5倍のゲイン)時間を提供することを発見しました。たとえば、アプリケーション内で特定の画面を開くには、NGENedデバッグの場合は0.3秒、JITデバッグの場合は0.5秒、NGENedリリースの場合は1.5秒、JITtedリリースの場合は2.5秒かかります。

JITコンパイル時のギャップは、JITコンパイラがリリースバイナリに対してより積極的な最適化を適用していることが原因であると私は理解します。私が知ることは、/p:DebugType/p:OptimizeスイッチがC#コンパイラに渡されることでデバッグとリリースの設定が異なりますが、でアプリケーションをビルドしても同じパフォーマンスの差が見られます。つまり、/p:Configuration=Debugと同じイメージデバッグオプションです。

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

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

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

+1

Release NGENedアセンブリのデバッグがまだ遅いため、JITが問題になっていますか?プロファイラを試すこともできます。また、#ifデバッグをコード内で使用していないことを確認してください。 – Guillaume

+1

SGENなしでXmlSerializerを使用していますか? http://stackoverflow.com/questions/771727/net-release-build-working-slower-than-debug – Guillaume

+0

私は '#if DEBUG'(これを反映するために編集された質問)を使用していません。リリースでは、アプリケーションの速度が必ずしも遅くなるわけではありません。速度は速いかもしれませんが、処理速度ではなく、低温起動時間を測定しています。私はダイナミックメソッドのJITtingを疑うので、それらの最適化レベルを決定するものを尋ねます。 – cynic

答えて

1

ここにいくつかの質問があります。 C#コンパイラに渡されたスイッチを最適化しますが、私は、アプリケーションをビルドする場合でも、同じ性能のギャップを参照してください :DEBUGTYPEと/ P:私は言う、デバッグおよび構成をリリースすることができるものから、

は /pで異なります/ config:Release/p:DebugType = full/p:Optimize = false - は、/ p:Configuration = Debugと同じイメージデバッグオプションです。

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

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

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

条件付きコンパイル機能を使用していない場合は、デバッグからリリースに切り替えても問題ありません。しかし、Releaseではパフォーマンス上のメリットが得られます。

NGENでは、2を超える利点を確認するために広範囲にテストすることをお勧めします。必ずしもパフォーマンスが向上するとは限りません。

+0

私は 'ConditionalAttribute'メソッドへの呼び出しは、JITではなく、ILへのコンパイルの段階で取り除かれると信じています。それにもかかわらず、私の場合の違いはJIT/NGENではなく、デバッグ/リリースです。 – cynic

+0

設定が同じであれば、DebugとReleaseの違いは何ですか? –

+0

はい。 PEには(DebuggableAttribute'を除いて)追加のフラグがありますか?そして、最も重要なことは、動的に生成されるコードにはどのレベルの最適化が適用されるかです。 – cynic

1

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

+0

コマンドラインから実行可能ファイルを実行して測定します。そうではありません。 – cynic

+0

Hrm。私はDEBUGよりもそれが_Slower_にならないと思う。 –

2

ロードする304アセンブリがある場合は、アプリは遅いです。 これは非常に多くのアセンブリが読み込まれているようです。

CLRがAppDomainにまだロードされていない別のアセンブリのコードに達するたびに、ディスクからロードする必要があります。

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

(特にReflectionを使用し、アセンブリのファイル名に決して変化しないもの)、すべてがマージされるのではないので、いくつかの実験が必要な場合があります。また、アセンブリが非常に大きくなることがあります。

+0

私は試してみますが、JITted DebugとNGENed Releaseの設定の速度の違いはほとんどありません。 SSDマシンでテストを実行します。 – cynic

関連する問題