デバッグとリリースのパフォーマンス


132

次の段落に遭遇しました:

「Visual StudioでコードをコンパイルするときにIDEでデバッグとリリースを設定しても、パフォーマンスにほとんど違いはありません。生成されたコードはほとんど同じです。C#コンパイラーは実際には最適化を行いません。C#コンパイラはIL ...を吐き出すだけで、実行時にすべての最適化を行うのはJITerです。JITerにはデバッグ/リリースモードがあり、パフォーマンスに大きな違いをもたらします。ただし、プロジェクトのデバッグ構成とリリース構成のどちらを実行しても、デバッガーが接続されているかどうかに関係しません。」

ソースはこちら、ポッドキャストはこちらです。

誰かが実際にこれを証明できるマイクロソフトの記事に私を導くことができますか?

C#デバッグvsリリースパフォーマンス」をグーグルすると、ほとんどの場合デバッグでパフォーマンスに大きな影響がある」、「リリースが最適化されている」、「デバッグを本番環境にデプロイしない」という結果が返されます。



Win7-x86の.Net4では、メインループにアサートなどがないデバッグよりもリリースが2倍近く高速に実行できる、私が書いたCPU限定プログラムがあります。
Bengie、2012年

また、メモリ使用量を気にする場合は、大きな違いが生じる可能性があります。デバッグモードでコンパイルされたマルチスレッドWindowsサービスがスレッドごとに700MBを使用するのに対し、リリースビルドではスレッドごとに50MBを使用するケースを見てきました。デバッグビルドは、通常の使用条件下ですぐにメモリ不足になりました。
o。2014

@Bengie-リリースビルドにデバッガーをアタッチした場合でも、2倍速く実行されることを確認しましたか?上記の引用は、JIT最適化がデバッガーが接続されているかどうかに影響されることを示していることに注意してください
ToolmakerSteve

回答:


99

部分的に正しい。デバッグモードでは、コンパイラーはすべての変数のデバッグシンボルを発行し、コードをそのままコンパイルします。リリースモードでは、いくつかの最適化が含まれています。

  • 未使用の変数はまったくコンパイルされません
  • 一部のループ変数は、不変であることが証明された場合、コンパイラーによってループから取り出されます。
  • #debugディレクティブで記述されたコードは含まれていません。

残りはJIT次第です。

最適化の全リストここでの礼儀エリックリッペルト


10
そして、Debug.Assertsを忘れないでください!DEBUGビルドでは、失敗した場合、スレッドを停止してメッセージボックスをポップアップします。リリースでは、まったくコンパイルされません。これは、[ConditionalAttribute]を持つすべてのメソッドに適用されます。
Ivan Zlatanov 2010年

13
C#コンパイラは末尾呼び出しの最適化を行いません。ジッタはします。あなたが最適化スイッチがオンのとき、C#コンパイラが何をするかの正確なリストが必要な場合は、参照blogs.msdn.com/ericlippert/archive/2009/06/11/...
エリックリペットに

63

パフォーマンスの質問について何かを「証明」する記事はありません。変更のパフォーマンスへの影響についてのアサーションを証明する方法は、両方の方法を試し、現実的ではあるが制御された条件下でテストすることです。

あなたはパフォーマンスについて質問しているので、明らかにパフォーマンスに関心があります。パフォーマンスを重視する場合は、パフォーマンスの目標を設定し、それらの目標に対する進捗状況を追跡するテストスイートを自分で作成するのが適切です。このようなテストスイートを作成したら、簡単に使用して、「デバッグビルドが遅い」などのステートメントの真偽をテストできます。

さらに、有意義な結果を得ることができます。「遅い」は、1マイクロ秒遅いか20分遅いかが明確でないため、意味がありません。「現実的な条件下では10%遅くなる」のがより意味があります。

この質問をオンラインで調査して、質問に答えるデバイスを構築するのに費やした時間を費やしてください。そうすれば、はるかに正確な結果が得られます。あなたがオンラインで読むもの起こるについての推測にすぎません。プログラムがどのように動作するかについて他の人が推測するのではなく、自分で収集した事実からの理由。


2
パフォーマンスを気にしながらも、「デバッグ」を使いたいと思うかもしれません。たとえば、ほとんどの時間が依存関係で待機している場合、デバッグモードでビルドしても大きな違いはないと思いますが、スタックトレースで行番号を取得するという追加の利点があります。幸せなユーザー。重要な点は、長所と短所を比較検討する必要があることであり、一般的な「デバッグでの実行は遅くなりますが、CPUにバインドされている場合のみ」というステートメントで十分です。
Josh Mouch

11

パフォーマンスについてコメントすることはできませんが、デバッグコードは通常、大規模な製品ではかなり多くの異なる動作をするため、「デバッグを本番環境にデプロイしないでください」というアドバイスは依然として当てはまります。1つには、デバッグスイッチをアクティブにして、もう1つには、プロダクションコードに属さない追加の冗長性チェックとデバッグ出力がある可能性があります。


私はその問題についてあなたに同意します、しかしこれは主要な質問に答えません
sagie

5
@sagie:はい、私はそれを知っていますが、ポイントはまだ作る価値があると思いました。
Konrad Rudolph

6

MSDNソーシャルから

それは十分に文書化されていません、これが私が知っていることです。コンパイラーはSystem.Diagnostics.DebuggableAttributeのインスタンスを発行します。デバッグバージョンでは、IsJitOptimizerEnabledプロパティはTrue、リリースバージョンではFalseです。この属性は、ildasm.exeを使用してアセンブリマニフェストで確認できます。

JITコンパイラはこの属性を使用して、デバッグを困難にする最適化を無効にします。ループ不変の巻き上げのようにコードを移動するもの。一部のケースでは、これによりパフォーマンスに大きな違いが生じる可能性があります。通常はありませんが。

ブレークポイントを実行アドレスにマッピングすることはデバッガーの仕事です。アドレスマッピングをコード化するIL命令を提供するJITコンパイラによって生成された.pdbファイルと情報を使用します。独自のデバッガーを作成する場合は、ICorDebugCode :: GetILToNativeMapping()を使用します。

JITコンパイラの最適化が無効になっているため、基本的にデバッグの展開は遅くなります。


3

あなたが読んだものは非常に有効です。デバッグコード(#IF DEBUGまたは[Conditional( "DEBUG")])を含まないJIT最適化により、リリースは通常よりリーンです。最小限のデバッグシンボルの読み込みであり、多くの場合、読み込み時間を短縮する小さなアセンブリは考慮されません。VSでコードを実行すると、ロードされるPDBとシンボルがより広範囲になるため、パフォーマンスの違いはより明白になりますが、独立して実行すると、パフォーマンスの違いがあまり明確にならない場合があります。特定のコードは他よりも最適化され、他の言語と同じように同じ最適化ヒューリスティックを使用しています。

スコットはインラインメソッド最適化についてここで良い説明をしています

デバッグとリリースの設定がASP.NET環境で異なる理由を簡単に説明しているこの記事を参照してください。


3

パフォーマンスについて、そしてデバッガーが接続されているかどうかについて、注意すべき点が1つあります。

多くのタイトなループを含むコードの一部があり、デバッグに永遠にかかるように見えましたが、それだけで十分に実行されました。つまり、問題が発生している顧客やクライアントは存在しませんでしたが、デバッグしていると、糖蜜のように実行されているように見えました。

犯人はDebug.WriteLineタイトなループの1つにあり、デバッグセッションからしばらく前に残された何千ものログメッセージを吐き出しました。デバッガーが接続され、そのような出力をリッスンすると、プログラムの速度を低下させるオーバーヘッドが含まれるようです。この特定のコードの場合、実行時間はそれ自体で約0.2〜0.3秒であり、デバッガーが接続されたときは30秒以上でした。

ただし、簡単な解決策は、不要になったデバッグメッセージを削除するだけです。


2

MSDNサイト...

リリースとデバッグの構成

プロジェクトの作業中は、通常、デバッグ構成を使用してアプリケーションをビルドします。この構成により、変数の値を表示し、デバッガーで実行を制御できるためです。また、リリース構成でビルドを作成およびテストして、1つのタイプのビルドまたは他のタイプのビルドでのみ現れるバグが発生していないことを確認することもできます。.NET Frameworkプログラミングでは、このようなバグは非常にまれですが、発生する可能性があります。

アプリケーションをエンドユーザーに配布する準備ができたら、リリースビルドを作成します。リリースビルドは、対応するデバッグ構成よりもはるかに小さく、通常ははるかに優れたパフォーマンスになります。ビルド構成は、プロジェクトデザイナーの[ビルド]ペインまたは[ビルド]ツールバーで設定できます。詳細については、ビルド構成を参照してください。


1

それは、アプリがコンピュートバインドされているかどうかに大きく依存し、Lasseの例のように、簡単に判別できるとは限りません。それが何をしているのかについて少しだけ質問がある場合は、数回一時停止してスタックを調べます。私が本当に必要としなかった何か特別なことが起こっている場合、それはすぐにそれを見つけます。


1

最近、パフォーマンスの問題に遭遇しました。製品の完全なリストは、時間がかかりすぎて約80秒でした。私はDBを調整し、クエリを改善しましたが、違いはありませんでした。TestProjectを作成することにしましたが、同じプロセスが4秒で実行されることがわかりました。次に、プロジェクトがデバッグモードであり、テストプロジェクトがリリースモードであることに気付きました。メインプロジェクトをリリースモードに切り替えたところ、製品の完全なリストはすべての結果を表示するのに4秒しかかかりませんでした。

概要:デバッグモードはデバッグ情報を保持するため、実行モードよりもはるかに低速です。常にリリースモードで展開する必要があります。.PDBファイルを含めれば、デバッグ情報を保持できます。これにより、たとえば、行番号でエラーを記録できます。


「実行モード」とは「リリース」を意味しますか?
ロンクライン

はい、正確に。リリースには、すべてのデバッグオーバーヘッドはありません。
Francisco Goldenstein 2012

1

デバッグモードとリリースモードには違いがあります。Fuzzlynツールがあります。これは、Roslynを使用してランダムなC#プログラムを生成するファザーです。.NETコアでこれらのプログラムを実行し、デバッグモードとリリースモードでコンパイルしたときに同じ結果が得られるようにします。

このツールを使用すると、多くのバグが見つかり、報告されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.