Ausnahmen, die die Leistung in Python beeinträchtigen

7

Ich weiß, Ausnahmen in Python sind schnell, wenn es um die try geht, aber es kann teuer sein, wenn es um den Fang geht.

Bedeutet das:

%Vor%

ist schneller als das?

%Vor%     
maazza 15.04.2016, 08:57
quelle

4 Antworten

8

Zusätzlich zu Francescos Antwort scheint es, dass einer der (relativ) teuren Teil des Fangs die Ausnahme ist, die passt:

%Vor%

Betrachten Sie die (CPython 2) -Demontage:

%Vor%

Beachten Sie, dass der catch-Block die Exception trotzdem lädt und sie mit einer KeyError vergleicht. In der Tat betrachten wir den except KeyError as ke -Fall:

%Vor%

Der einzige Unterschied ist ein einzelner STORE_FAST , um den Ausnahmewert zu speichern (im Falle einer Übereinstimmung). Ähnliches mit mehreren Ausnahmeübereinstimmungen:

%Vor%

Vervielfältigt die Exception und versucht, sie mit jeder aufgelisteten Exception zu vergleichen, bis eine Übereinstimmung gefunden wird, was (wahrscheinlich) als "schlechte Fangleistung" bezeichnet wird.

    
val 20.04.2016, 08:41
quelle
6

Ich denke, die beiden sind in Bezug auf die Geschwindigkeit gleich:

%Vor%     
Francesco 15.04.2016 09:11
quelle
3

Ein Python-Programm wird aus Codeblöcken konstruiert. Ein Block ist ein Stück Python-Programmtext, der als eine Einheit ausgeführt wird. In Python wird der Kernblock als struct basisblock dargestellt:

cpython / Python / compile.c

%Vor%

Schleifen, try / except und try / finally-Anweisungen haben etwas anderes gehandhabt. Für diese 3 Anweisungen werden Rahmenblock verwendet:

cpython / Python / compile.c

%Vor%

Ein Codeblock wird in einem Ausführungsrahmen ausgeführt.

cpython / Include / frameobject.h

%Vor%

Ein Rahmen enthält einige administrative Informationen (die zum Debuggen verwendet werden) und bestimmt, wo und wie die Ausführung fortgesetzt wird, nachdem die Ausführung des Codeblocks abgeschlossen ist. Wenn Sie die Anweisung 'as' verwenden (in den Anweisungen 'Importiere etwas als' oder 'Ausnahme Ausnahme als'), benennen Sie einfach den Bindungsvorgang. I.e. Python fügt einfach einen Verweis auf das Objekt in der * f_locals-Symboltabelle des Rahmenobjekts hinzu. Also kein Overhead zur Laufzeit wird nicht sein.

Aber Sie werden bei der Analyse Zeit haben.

cpython / Module / parsermodule.c

%Vor%

Aber meiner Meinung nach kann das vernachlässigt werden

    
Nikita Klimov 21.04.2016 07:38
quelle
3

Der Catch ist nicht teuer, die Teile, die relativ langsam erscheinen, sind die Erstellung des Stack-Trace selbst und bei Bedarf das anschließende Abwickeln des Stacks.

Jede Stapel-basierte Sprache, von der ich weiß, dass Sie Stack-Traces erfassen können, muss diese Operationen ausführen.

  1. Wenn raise aufgerufen wird, sammeln Sie die Stapelinformationen. Beachten Sie, dass Sie mit Java 1.7 die Stack-Sammlung unterdrücken können und es ist viel schneller, aber Sie verlieren eine Menge nützlicher Informationen. Es gibt keinen vernünftigen Weg für die Sprache zu wissen, wer es fängt, so dass das Ignorieren einer Ausnahme nicht hilft, weil sie ohnehin den größten Teil der Arbeit leisten muss.
  2. Wenn wir eine Ausnahme auslösen, dann entpacken Sie den Stack, dh geben Sie den gesamten Speicher frei und gehen Sie zurück, bis wir einen gültigen Catch erhalten haben.

Der Fang ist im Vergleich zu den beiden obigen Operationen winzig. Hier ist ein Code, der zeigt, dass die Leistung abnimmt, wenn die Stack-Tiefe zunimmt.

%Vor%

Die Ausgabe ist, Zeit (Zeiten sind relativ), um Exception()

aufzurufen %Vor%

Jemand, der in Python besser ist als ich, könnte py.test bekommen, um die Zeiten am Ende zu drucken.

Hinweis: Vor einigen Wochen wurde eine ähnliche Frage zu Java gestellt. Es ist ein sehr informativer Thread unabhängig von der verwendeten Sprache ...

Welcher Teil des Auslösens einer Ausnahme ist teuer?

    
Harry 22.04.2016 04:15
quelle