Ist ein Versuch und Fang, der keine Ausnahme auslöst, effizienter als eine Bedingung?

8

Ich bin kürzlich auf dieses Beispiel gestoßen:

Wenn 999 mal von 1.000 eine Ausnahme nicht ausgelöst wird, wird die Ausnahme nur einmal generiert. Andererseits wäre eine Bedingung 999 Mal unnötig aufgerufen worden, daher ist in diesem Fall die Ausnahme überlegen.

In diesem Fall ist es C #, aber im Allgemeinen ist das wahr? Ich hatte zuvor angenommen, dass Try / Catch-Anweisungen einen eigenen Overhead haben, der der Zeit entspricht, die für die Bearbeitung einer Bedingung aufgewendet wird.

Zugegeben, nur Try / Catch-Blöcke an einen Ort zu werfen, an den eine Bedingung normalerweise gehen würde, wäre ein schrecklicher Weg, um zu codieren, aber in Bezug auf die Ressourcen hält diese Aussage?

Jane Panda
quelle
Wie implementiert der Compiler try / catch? Ich vermute, es ist etwas komplizierter als ein einfaches if ().
Dan Pichelman
8
Versuch es. Probieren Sie es wirklich aus. Warum glaubst du etwas, was eine zufällige Person im Internet gesagt hat? Zu wissen, wie häufig Elemente in der Sprache Ihrer Wahl die Leistung vergleichen, ist den begrenzten Aufwand wert, einmal ein sorgfältiges Experiment durchzuführen.
Kilian Foth
Ich fand, dass das Schreiben eines Leistungsvergleichs eine sehr einfache Aufgabe ist, insbesondere eine abstrakte. auch das Beispiel ist aus einem C # Lehrbuch
Jane Panda
2
Ich werde den erforderlichen Kommentar "Schreibbaren Code schreiben und nicht vorzeitig optimieren" machen.
Djechlin
1
@djechlin Jemand musste; )
Jane Panda

Antworten:

4

Dies gilt im Allgemeinen für Compiler in kommerzieller Qualität. Bedingungen können jedoch ähnliche Effizienzen unter Verwendung von assume(false)Annotationen im Stil erzielen . Die profilgesteuerte Optimierung kann beide übertreffen.

Der Grund dafür ist, dass gute Compiler effizienteren Code generieren können, indem sie korrekte Annahmen über die Wahrscheinlichkeit der Ausführung von Code treffen. Da die Konvention besagt, dass Ausnahmen außergewöhnlich sind, generieren die meisten Compiler (ohne Profildaten) Code, der optimal ist, wenn Ausnahmen tatsächlich selten sind.

Beispielsweise kann der Ausnahmebehandlungscode in ein eigenes Segment eingefügt und nur ausgelagert werden, wenn die erste Ausnahme auftritt. Dies bedeutet, dass der CPU-Cache effizienter genutzt werden kann und nur nicht außergewöhnlichen Code gespeichert wird.

MSalters
quelle
Und dynamische Compiler, wie sie beispielsweise in fast allen JavaScript-Engines, JVMs und Smalltalk-Implementierungen zu finden sind, müssen nicht einmal Annahmen über die Wahrscheinlichkeit von Verzweigungen treffen, sondern können sie nur zählen. Das ist wie PGO auf Steroiden: Reprofilierung und Wieder Optimierung immer und immer und immer und immer wieder, die mit realer Arbeitsbelastung , die ausgeführt werden jetzt zu führen , den Code zu optimieren , die ausgeführt werden jetzt .
Jörg W Mittag
4

Es gibt Szenarien, in denen try / catch und andere Bedingungen verwendet werden.

Mit einem try / catch nicht der Leistung nicht beeinträchtigt werden, wie ausführlich dargelegt Hier

Die Gesamtkosten eines try ... catch-Blocks, der niemals eine Ausnahme behandelt, betragen einige Byte Speicher

Über die Leistung hinaus ist eine ordnungsgemäße Ausnahmebehandlung wichtig. Das Letzte, was Sie möchten, sind nicht erfasste Fehler, die einem Benutzer angezeigt werden, fehlerhafte Leistung oder die Anwendung, die hängen bleibt, nachdem ein Problem aufgetreten ist.

Erich
quelle
3
+1 Leistung ist nicht das einzige,
worüber
2
Das ist eine gute Lektüre in Bezug auf Ausnahmen.
Jane Panda
-1

Ein Beispiel für eine bessere Leistung bei Verwendung von try / catch anstelle einer Bedingung ist der Umgang mit Wörterbüchern. Wenn Sie fragen, ob der Schlüssel O (n) enthält, versuchen Sie einfach, auf den Schlüssel zuzugreifen / ihn hinzuzufügen und die potenzielle Ausnahme abzufangen.

try
{
    dict.Add(key, val);
}
catch (Exception)
{

    dict[key] = val;
}
Enrique Medina
quelle
Wow, wenn das stimmt, bin ich wirklich überrascht! Haben Sie eine Referenz?
5
-1. Tu das nicht. Wenn Sie Bedenken hinsichtlich des Leistungsaufwands bei der Überprüfung des vorhandenen Schlüssels haben, verwenden Sie stattdessen TryGetValue (). msdn.microsoft.com/en-us/library/bb347013.aspx
Riwalk
Vielen Dank für den Hinweis, dass ich zumindest eine schlechte Praxis empfehlen möchte. Ich benutze das aber schon lange, ein guter Habbit, der wohl veraltet ist. Mein Ziel war es jedenfalls zu zeigen, dass es Szenarien gibt, in denen das Abfangen einer Ausnahme eine bessere Option ist, als zu fragen, ob es gültig ist, etwas zu tun.
Enrique Medina