Frage

Welche Auswirkungen auf die Leistung gibt es zu berücksichtigen, wenn Try-catch-Anweisungen in PHP 5 verwenden?

Ich habe vor, die im Internet einiger alte und scheinbar widersprüchlichen Informationen zu diesem Thema lesen. Ein großer Teil der Rahmen mit ich zur Zeit arbeiten müssen, wurde 4 auf PHP erstellt und 5. viele der Feinheiten von PHP fehlt Also, ich habe mich nicht viel Erfahrung im Umgang mit Try-Fängen einhergehen mit PHP.

War es hilfreich?

Lösung

Eine Sache zu prüfen ist, dass die Kosten eines Try-Block, wo keine Ausnahme ausgelöst wird, von den Kosten der tatsächlich das Werfen und Fangen eine Ausnahme eine andere Frage ist.

Wenn Ausnahmen nur in Fehlerfällen geworfen werden, Sie mit ziemlicher Sicherheit kümmern sich nicht um Leistung, da Sie nicht sehr viele Male pro Ausführung Ihres Programms fehl. Wenn Sie in einer engen Schleife sind Fehler (a.k.a: Kopf gegen eine Mauer hämmern), Ihre Anwendung hat wahrscheinlich schlimmere Probleme als langsam zu sein. Also keine Sorge über die Kosten des Auslösens eine Ausnahme, wenn Sie irgendwie gezwungen sind, sie für regelmäßigen Kontrollfluss zu verwenden.

Jemand hat eine Antwort sprechen über Code Profilierung, die eine Ausnahme auslöst. Ich habe getestet es nie selbst, aber ich sage voraus, zuversichtlich, dass dies eine viel größere Leistungseinbußen zeigt als nur in gehen und aus einem try-Block, ohne etwas zu werfen.

Eine andere Sache zu prüfen ist, dass, wo Sie nisten viele Ebenen tief nennt, kann es sogar noch schneller sein, einen einzigen Versuch zu haben ... fangen direkt an der Spitze, als es ist Rückgabewerte zu überprüfen und propagieren Fehler bei jedem Aufruf .

Im Gegensatz zu dieser Situation, wo Sie feststellen, dass Sie jeden Anruf in seinem eigenen try ... catch-Block sind Einwickeln, wird Ihr Code langsamer. Und hässlicher.

Andere Tipps

Ich war gelangweilt und profiliert die folgenden (ich das Timing Code weggelassen):

function no_except($a, $b) { 
    $a += $b;
    return $a;
}
function except($a, $b) { 
    try {
        $a += $b;
    } catch (Exception $e) {}
    return $a;
}

mit zwei verschiedenen Schleifen:

echo 'no except with no surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    no_except(5, 7);
}
echo 'no except with surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    try {
        no_except(5, 7);
    } catch (Exception $e) {}
}
echo 'except with no surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    except(5, 7);
}
echo 'except with surrounding try';
for ($i = 0; $i < NUM_TESTS; ++$i) {
    try {
        except(5, 7);
    } catch (Exception $e) {}
}

Mit 1000000 läuft auf meinem WinXP-Box läuft Apache und PHP 5.2.6:

no except with no surrounding try = 3.3296
no except with surrounding try = 3.4246
except with no surrounding try = 3.2548
except with surrounding try = 3.2913

Diese Ergebnisse waren konsistent und in ähnlichem Anteil blieben unabhängig davon, welche die Tests liefen bestellen.

Fazit: Code Hinzufügen von seltenen Ausnahmen zu behandeln sind nicht langsamer als Code der ignorieren Ausnahmen

.

Try-Catch-Blöcke sind keine Performance-Problem -. Die reale Performance-Engpass kommt von Objekten Ausnahme zu schaffen

Testcode:

function shuffle_assoc($array) { 
    $keys = array_keys($array);
    shuffle($keys);
    return array_merge(array_flip($keys), $array);
}

$c_e = new Exception('n');

function no_try($a, $b) { 
    $a = new stdclass;
    return $a;
}
function no_except($a, $b) { 
    try {
        $a = new Exception('k');
    } catch (Exception $e) {
        return $a + $b;
    }
    return $a;
}
function except($a, $b) { 
    try {
        throw new Exception('k');
    } catch (Exception $e) {
        return $a + $b;
    }
    return $a;
}
function constant_except($a, $b) {
    global $c_e;
    try {
        throw $c_e;
    } catch (Exception $e) {
        return $a + $b;
    }
    return $a;
}

$tests = array(
    'no try with no surrounding try'=>function() {
        no_try(5, 7);
    },
    'no try with surrounding try'=>function() {
        try {
            no_try(5, 7);
        } catch (Exception $e) {}
    },
    'no except with no surrounding try'=>function() {
        no_except(5, 7);
    },
    'no except with surrounding try'=>function() {
        try {
            no_except(5, 7);
        } catch (Exception $e) {}
    },
    'except with no surrounding try'=>function() {
        except(5, 7);
    },
    'except with surrounding try'=>function() {
        try {
            except(5, 7);
        } catch (Exception $e) {}
    },
    'constant except with no surrounding try'=>function() {
        constant_except(5, 7);
    },
    'constant except with surrounding try'=>function() {
        try {
            constant_except(5, 7);
        } catch (Exception $e) {}
    },
);
$tests = shuffle_assoc($tests);

foreach($tests as $k=>$f) {
    echo $k;
    $start = microtime(true);
    for ($i = 0; $i < 1000000; ++$i) {
        $f();
    }
    echo ' = '.number_format((microtime(true) - $start), 4)."<br>\n";
}

Ergebnisse:

no try with no surrounding try = 0.5130
no try with surrounding try = 0.5665
no except with no surrounding try = 3.6469
no except with surrounding try = 3.6979
except with no surrounding try = 3.8729
except with surrounding try = 3.8978
constant except with no surrounding try = 0.5741
constant except with surrounding try = 0.6234

Im Allgemeinen verwenden eine Ausnahme gegen unerwartete Ausfälle zu schützen, und verwenden Sie Fehler vor Fehlern im Code überprüft, die Teil des normalen Programmzustand sind. Zur Veranschaulichung:

  1. Datensatz nicht in der Datenbank gefunden -. Gültigen Zustand, sollten Sie die Abfrageergebnisse und Messaging den Benutzer in geeigneter Weise überprüft

  2. SQL-Fehler beim Datensatz zu holen versuchen - unerwarteten Fehler, kann der Datensatz oder nicht da sein, aber Sie haben einen Programmfehler - das ist guter Ort für eine Ausnahme - lügen Fehler in Fehlerprotokoll, eine E-Mail an den Administrator der Stack-Trace, und zeigt den Benutzer eine höfliche Fehlermeldung ihn darauf hinweist, dass etwas schief gelaufen ist, und Sie sind daran zu arbeiten.

Ausnahmen sind teuer, aber wenn Sie Ihren gesamten Programmablauf mit ihnen umgehen soll jeder Unterschied in der Leistung nicht vom Menschen wahrnehmbar.

Ich habe nichts auf Try / Catch Leistung auf Google aber einen einfachen Test mit einer Schleife zu werfen Fehler anstelle einem IF-Anweisung produziert 329ms vs 6 ms in einer Schleife von 5000 gefunden.

Es tut uns leid zu einer sehr alten Nachricht zu schreiben, aber ich lese die Kommentare und ich stimme nicht etwas, der Unterschied könnte mit einfachen Stück Codes minimal sein, oder es könnte vernachlässigbaren sein, wo die Try / Catch für bestimmte Teile des Codes verwendet werden, das sind nicht immer vorhersehbar, aber ich glaube auch (nicht getestet), dass eine einfache:

if(isset($var) && is_array($var)){
    foreach($var as $k=>$v){
         $var[$k] = $v+1;
    }
}

ist schneller als

try{
    foreach($var as $k=>$v){
        $var[$k] = $v+1;
    }
}catch(Exception($e)){
}

Ich glaube auch (nicht getestet), dass ein:

<?php
//beginning code
try{
    //some more code
    foreach($var as $k=>$v){
        $var[$k] = $v+1;
    }
    //more code
}catch(Exception($e)){
}
//output everything
?>

ist teurer als im Code zusätzliche IFs haben

Das ist eine sehr gute Frage!

Ich habe es viele Male getestet und sehe nie ein Performance-Problem ;-) Es war richtig, vor 10 Jahren in C ++, aber ich denke, heute sind sie es seit ihrem so nützlich und sauberer viel verbessert haben.

Aber ich habe immer noch Angst meinen ersten Einstiegspunkt mit ihm zu umgeben:

try {Controller::run();}catch(...)

Ich nicht Test mit vielen Funktionen aufrufe und groß sind .... Ist jemand voll es testet bereits?

Im Allgemeinen sind sie teuer und nicht lohnt in PHP.

Da es eine gesichtete Ausdrücke Sprache ist, müssen Sie etwas fangen, die eine Ausnahme auslöst.

Wenn Sie mit Legacy-Code zu tun, die nicht, und neuem Code werfen das tut, es führt nur zu Verwirrung.

Viel Glück!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top