Debug vs. Release-Leistung

132

Ich bin auf folgenden Absatz gestoßen:

„Die Einstellung Debug vs. Release in der IDE beim Kompilieren Ihres Codes in Visual Studio hat fast keinen Einfluss auf die Leistung. Der generierte Code ist nahezu identisch. Der C # -Compiler führt keine wirkliche Optimierung durch. Der C # -Compiler spuckt nur IL aus… und zur Laufzeit übernimmt der JITer die gesamte Optimierung. Der JITer verfügt über einen Debug- / Release-Modus, der die Leistung erheblich verbessert. Das hängt jedoch nicht davon ab, ob Sie die Debug- oder Release-Konfiguration Ihres Projekts ausführen, sondern davon, ob ein Debugger angeschlossen ist. “

Die Quelle ist hier und der Podcast ist hier .

Kann mich jemand auf einen Microsoft-Artikel verweisen, der dies tatsächlich beweisen kann?

Wenn Sie " C # -Debug vs. Release-Leistung " googeln, werden meistens Ergebnisse zurückgegeben, die besagen, dass " Debug hat einen großen Leistungseinbruch ", " Release ist optimiert " und " Debug nicht für die Produktion bereitstellen ".

sagie
quelle
Mögliches Duplikat der Leistungsunterschiede zwischen Debug- und Release-Builds
Hans Passant
Mit .Net4 unter Win7-x86 habe ich ein Programm mit CPU-Begrenzung geschrieben, das in der Version fast zweimal schneller ausgeführt wird als das Debuggen ohne Asserts / etc in der Hauptschleife.
Bengie
Wenn Sie sich für die Speichernutzung interessieren, kann es auch große Unterschiede geben. Ich habe einen Fall gesehen, in dem ein im Debug-Modus kompilierter Windows-Dienst mit mehreren Threads 700 MB pro Thread verwendet hat, gegenüber 50 MB pro Thread im Release-Build. Dem Debug-Build ging unter typischen Nutzungsbedingungen schnell der Speicherplatz aus.
o. nate
@Bengie - Haben Sie überprüft, ob ein Debugger, der an den Release-Build angehängt wird, immer noch zweimal schneller ausgeführt wird? Beachten Sie, dass das obige Zitat besagt, dass die JIT-Optimierung davon abhängt, ob ein Debugger angeschlossen ist.
ToolmakerSteve

Antworten:

99

Teilweise wahr. Im Debug-Modus gibt der Compiler Debug-Symbole für alle Variablen aus und kompiliert den Code unverändert. Im Release-Modus sind einige Optimierungen enthalten:

  • Nicht verwendete Variablen werden überhaupt nicht kompiliert
  • Einige Schleifenvariablen werden vom Compiler aus der Schleife entfernt, wenn sich herausstellt, dass sie invariant sind
  • Code, der unter der Direktive #debug geschrieben wurde, ist nicht enthalten usw.

Der Rest liegt bei der GEG.

Vollständige Liste der Optimierungen hier mit freundlicher Genehmigung von Eric Lippert .

Adrian Zanescu
quelle
10
Und vergessen Sie nicht Debug.Asserts! Wenn sie im DEBUG-Build fehlschlagen, halten sie den Thread an und öffnen ein Meldungsfeld. In der Version werden sie überhaupt nicht kompiliert. Dies gilt für alle Methoden mit [ConditionalAttribute].
Ivan Zlatanov
13
Der C # -Compiler führt keine Tail-Call-Optimierungen durch. der Jitter tut es. Wenn Sie eine genaue Liste der Funktionen des C # -Compilers wünschen, wenn der Optimierungsschalter aktiviert
Eric Lippert
63

Es gibt keinen Artikel, der etwas über eine Leistungsfrage "beweist". Der Weg, um eine Aussage über die Auswirkungen einer Änderung auf die Leistung zu beweisen, besteht darin, sie in beide Richtungen auszuprobieren und unter realistischen, aber kontrollierten Bedingungen zu testen.

Sie stellen eine Frage zur Leistung, also ist Ihnen die Leistung klar. Wenn Sie sich für Leistung interessieren, ist es das Richtige, einige Leistungsziele festzulegen und sich dann eine Testsuite zu schreiben, die Ihren Fortschritt anhand dieser Ziele verfolgt. Sobald Sie eine solche Testsuite haben, können Sie sie leicht verwenden, um die Wahrheit oder Falschheit von Aussagen wie "Der Debug-Build ist langsamer" selbst zu testen.

Darüber hinaus können Sie aussagekräftige Ergebnisse erzielen. "Langsamer" ist bedeutungslos, da nicht klar ist, ob es eine Mikrosekunde langsamer oder zwanzig Minuten langsamer ist. "10% langsamer unter realistischen Bedingungen" ist sinnvoller.

Verbringen Sie die Zeit, die Sie damit verbracht hätten, diese Frage online zu recherchieren, um ein Gerät zu bauen, das die Frage beantwortet. Auf diese Weise erhalten Sie weitaus genauere Ergebnisse. Alles, was Sie online lesen, ist nur eine Vermutung darüber, was passieren könnte . Grund dafür sind Fakten, die Sie selbst gesammelt haben, und nicht die Vermutungen anderer, wie sich Ihr Programm verhalten könnte.

Eric Lippert
quelle
2
Ich denke, Sie können sich um die Leistung kümmern und haben dennoch den Wunsch, "Debug" zu verwenden. Wenn zum Beispiel die meiste Zeit auf Abhängigkeiten wartet, wird das Erstellen im Debug-Modus meiner Meinung nach keinen großen Unterschied machen, aber Sie haben den zusätzlichen Vorteil, dass Zeilennummern in Stapelspuren angezeigt werden, wodurch Fehler schneller behoben und behoben werden können glücklichere Benutzer. Der Punkt ist, dass Sie die Vor- und Nachteile abwägen müssen und eine allgemeine Anweisung "Debug läuft langsamer, aber nur, wenn Sie CPU-gebunden sind" ausreicht, um bei der Entscheidung zu helfen.
Josh Mouch
11

Ich kann die Leistung nicht kommentieren, aber der Ratschlag „Debuggen nicht für die Produktion bereitstellen“ gilt immer noch, weil Debug-Code in großen Produkten normalerweise einige Dinge anders macht. Zum einen sind möglicherweise Debug-Schalter aktiv, zum anderen werden wahrscheinlich zusätzliche redundante Überprüfungen und Debug-Ausgaben durchgeführt, die nicht zum Produktionscode gehören.

Konrad Rudolph
quelle
Ich stimme Ihnen in dieser Frage zu, aber dies beantwortet nicht die Hauptfrage
sagie
5
@sagie: Ja, das ist mir bewusst, aber ich dachte, der Punkt lohnt sich immer noch.
Konrad Rudolph
6

Von msdn social

Es ist nicht gut dokumentiert, hier ist was ich weiß. Der Compiler gibt eine Instanz des System.Diagnostics.DebuggableAttribute aus. In der Debug-Version ist die IsJitOptimizerEnabled-Eigenschaft True, in der Release-Version False. Sie können dieses Attribut im Assemblymanifest mit ildasm.exe sehen

Der JIT-Compiler verwendet dieses Attribut, um Optimierungen zu deaktivieren, die das Debuggen erschweren würden. Diejenigen, die Code wie schleifeninvariantes Heben bewegen. In ausgewählten Fällen kann dies einen großen Leistungsunterschied bewirken. Normalerweise aber nicht.

Das Zuordnen von Haltepunkten zu Ausführungsadressen ist Aufgabe des Debuggers. Es verwendet die vom JIT-Compiler generierte PDF-Datei und die Informationen, die den IL-Befehl zum Codieren der Adresszuordnung bereitstellen. Wenn Sie Ihren eigenen Debugger schreiben würden, würden Sie ICorDebugCode :: GetILToNativeMapping () verwenden.

Grundsätzlich ist die Debug-Bereitstellung langsamer, da die JIT-Compiler-Optimierungen deaktiviert sind.

Neil
quelle
3

Was Sie lesen, ist durchaus gültig. Die Freigabe ist aufgrund der JIT-Optimierung in der Regel schlanker, ohne Debug-Code (#IF DEBUG oder [Conditional ("DEBUG")]), minimales Laden von Debug-Symbolen und wird häufig nicht berücksichtigt, da kleinere Assemblys die Ladezeit verkürzen. Eine andere Leistung ist beim Ausführen des Codes in VS aufgrund umfangreicherer PDBs und geladener Symbole offensichtlicher. Wenn Sie ihn jedoch unabhängig ausführen, sind die Leistungsunterschiede möglicherweise weniger offensichtlich. Bestimmte Codes optimieren besser als andere und verwenden dieselben Optimierungsheuristiken wie in anderen Sprachen.

Scott hat eine gute Erklärung auf Inline - Methode Optimierung hier

In diesem Artikel wird kurz erläutert, warum sich die Einstellungen für Debug und Release in der ASP.NET-Umgebung unterscheiden.

Fadrian Sudaman
quelle
3

Eine Sache, die Sie beachten sollten, was die Leistung betrifft und ob der Debugger angeschlossen ist oder nicht, hat uns überrascht.

Wir hatten einen Code, der viele enge Schleifen enthielt, deren Debugging ewig zu dauern schien, der jedoch von sich aus recht gut lief. Mit anderen Worten, keine Kunden oder Kunden hatten Probleme, aber beim Debuggen schien es wie Melasse zu laufen.

Der Schuldige war einer Debug.WriteLinein einer der engen Schleifen, die Tausende von Protokollnachrichten ausspuckten, die vor einiger Zeit von einer Debug-Sitzung hinterlassen wurden. Es scheint, dass, wenn der Debugger angehängt ist und solche Ausgaben abhört, Overhead entsteht, der das Programm verlangsamt. Für diesen bestimmten Code lag die Laufzeit allein in der Größenordnung von 0,2 bis 0,3 Sekunden und mehr als 30 Sekunden, wenn der Debugger angehängt wurde.

Einfache Lösung: Entfernen Sie einfach die nicht mehr benötigten Debug-Meldungen.

Lasse V. Karlsen
quelle
2

In msdn Seite ...

Release vs. Debug-Konfigurationen

Während Sie noch an Ihrem Projekt arbeiten, erstellen Sie Ihre Anwendung normalerweise mithilfe der Debug-Konfiguration, da Sie mit dieser Konfiguration den Wert von Variablen anzeigen und die Ausführung im Debugger steuern können. Sie können Builds auch in der Release-Konfiguration erstellen und testen, um sicherzustellen, dass Sie keine Fehler eingeführt haben, die nur bei dem einen oder anderen Build-Typ auftreten. In der .NET Framework-Programmierung sind solche Fehler sehr selten, können jedoch auftreten.

Wenn Sie bereit sind, Ihre Anwendung an Endbenutzer zu verteilen, erstellen Sie einen Release-Build, der viel kleiner ist und normalerweise eine viel bessere Leistung als die entsprechende Debug-Konfiguration aufweist. Sie können die Build-Konfiguration im Build-Bereich des Projekt-Designers oder in der Build-Symbolleiste festlegen. Weitere Informationen finden Sie unter Erstellen von Konfigurationen.

Hallie
quelle
1

Dies hängt in hohem Maße davon ab, ob Ihre App rechengebunden ist, und es ist nicht immer leicht zu erkennen, wie im Beispiel von Lasse. Wenn ich die geringste Frage dazu habe, was es tut, halte ich es einige Male an und untersuche den Stapel. Wenn etwas Besonderes los ist, das ich nicht wirklich brauchte, wird es sofort erkannt.

Mike Dunlavey
quelle
1

Ich bin kürzlich auf ein Leistungsproblem gestoßen. Die vollständige Liste der Produkte dauerte zu lange, etwa 80 Sekunden. Ich habe die Datenbank optimiert, die Abfragen verbessert und es gab keinen Unterschied. Ich entschied mich für ein TestProjekt und stellte fest, dass der gleiche Prozess in 4 Sekunden ausgeführt wurde. Dann wurde mir klar, dass sich das Projekt im Debug-Modus und das Testprojekt im Release-Modus befand. Ich habe das Hauptprojekt in den Release-Modus geschaltet und die vollständige Liste der Produkte dauerte nur 4 Sekunden, um alle Ergebnisse anzuzeigen.

Zusammenfassung: Der Debug-Modus ist weitaus langsamer als der Ausführungsmodus, da weiterhin Informationen debuggt werden. Sie sollten immer im Relase-Modus bereitstellen. Sie können weiterhin Debugging-Informationen haben, wenn Sie .PDB-Dateien einschließen. Auf diese Weise können Sie beispielsweise Fehler mit Zeilennummern protokollieren.

Francisco Goldenstein
quelle
Mit "Run Mode" meinen Sie "Release"?
Ron Klein
Ja genau. Release hat nicht den gesamten Debug-Overhead.
Francisco Goldenstein
1

Debug- und Release-Modi weisen Unterschiede auf. Es gibt ein Tool Fuzzlyn : Es ist ein Fuzzer, der Roslyn verwendet, um zufällige C # -Programme zu generieren. Es führt diese Programme auf .NET Core aus und stellt sicher, dass sie beim Kompilieren im Debug- und Release-Modus dieselben Ergebnisse liefern.

Mit diesem Tool wurden viele Fehler gefunden und gemeldet.

Sergey Ponomarev
quelle