Optimierung durch logische Reihenfolge in if-Anweisungen

Logische Operatoren in if-Anweisungen werden von PHP beim Interpretieren von links nach rechts ausgewertet. Der Verdacht liegt also nahe, dass sich eine logisch sinnvolle Reihenfolge mit AND bzw. && verknüpfter Bedingungen positiv auf die Performance Ihres PHP-Scripts auswirkt. Wir erwarten also, dass es bei zwei verknüpften Bedingungen innerhalb der if-Anweisung sinnvoller ist, die kostengünstigere Bedingung als erste Bedingung zu verwenden.

Da „richtig” und „falsch” bzw. „optimal” und „nicht optimal” in erster Linie von der Logik der if-Anweisung abhängig und somit ein weites Feld sind, beschränken wir uns bei den Benchmarks auf zwei einfache Scripte als Beleg unserer Vermutung.

Zu berücksichtigen sind nicht nur die Kosten der Überprüfung einer Bedingung – ein Vergleichsoperator ist günstiger als ein Funktionsaufruf – sondern vor allem auch die Wahrscheinlichkeit der Erfüllung bzw. Nicht-Erfüllung der jeweiligen Bedingung.

Vergleichsoperator gefolgt von Funktion

Code:

<?php
for ($i = 0;$i < 10000;$i++) {
    if (1 === 2 && file_exists("./beispiel.php")) {
        echo "Bedingung erfüllt";
    }
}
?>

Erläuterung:
Innerhalb einer for()-Schleife wird 10.000mal eine if-Anweisung ausgewertet. In dieser steht als erste Bedingung der nicht erfüllbare Vergleich 1===2. Dieser Vergleich ist durch && mit der zweiten Bedingung file_exists("./beispiel.php") verknüpft, die die Existenz einer Datei überprüft. Ob diese Datei existiert oder nicht, spielt in diesem Fall ebenso wenig eine Rolle wie der innerhalb der geschweiften Klammern bei Zutreffen beider Bedingungen auszuführende Code.

Funktion gefolgt von Vergleichsoperator

Code:

<?php
for ($i = 0;$i < 10000;$i++) {
    if (file_exists("./beispiel.php") && 1 === 2) {
        echo "Bedingung erfüllt";
    }
}
?>

Erläuterung:
Wir haben das Script geringfügig modifiziert, indem wir die beiden Bedingungen in der if-Anweisung „vertauscht” haben. Es wird nun zunächst geprüft, ob die Datei beispiel.php existiert und als zweite Bedingung wird der zuvor als erste Bedingung, aber nach wie vor unerfüllbare Vergleich 1===2 verwendet.

Ergebnis

Requests per second (RPS)Time per Request (TPR)Vergleich
Vergleichsoperator gefolgt von Funktion213.33 [#/sec] (mean)4.688 [ms] (mean)
4907.7%
98.0%
Funktion gefolgt von Vergleichsoperator4.26 [#/sec] (mean)235.000 [ms] (mean)

Das Script, bei dem die erste Bedingung in der if-Anweisung der Vergleich mittels des ===-Operators ist, kann rund 50mal so schnell ausgeführt werden wie der Code, bei dem die erste Bedingung innerhalb der if-Anweisung eine Funktion ist.

Fazit

Die beiden Beispiel-Scripte haben unsere Vermutung bestätigt und gezeigt, wie wichtig eine logisch sinnvolle Reihenfolge von Bedingungen in if-Anweisungen für die optimierte Programmierung von PHP-Scripten ist. Die vorgenommene Änderung ist denkbar einfach, ohne jegliche Auswirkungen auf die Funktionalität des Codes und hat in unserem Beispiel die Performance um rund das 50fache gesteigert.

Natürlich haben wir in unserem Beispiel mit file_exists() eine relativ „teure” Funktion und mit 1===2 einen in der Praxis sinnlosen Vergleich gewählt. Die Logik des Optimierungs-Tipps und das Potential zur Performance-Steigerung sollten die beiden Beispiel-Scripte jedoch eindrucksvoll demonstrieren.

 

Anmerkung:
Die Tests wurden mit dem Apache HTTP server benchmarking tool ab auf einem im Februar 2017 nicht mehr dem Stand der Technik entsprechenden Server durchgeführt. Die RPS und TPR der getesteten PHP-Scripte sollten auf einem im Produktiv-Einsatz befindlichen Webserver deutlich besser sein.

Nächster Tipp:

Die Beachtung von Wahrscheinlichkeiten bei der Reihenfolge in if-Anweisungen bietet auf einfache Weise großes Einsparpotenzial hinsichtlich der Performance. Dass bestimmte Coding-Conventions dem entgegen stehen, ist eher unüblich. Beim nächsten Tipp zur Optimierung zerlegen wir einen String in PHP.

Optimierung durch Zerlegen von Strings mit explode()

Optimierung durch Zerlegen von Strings mit explode()

Soll ein String anhand eines Teilstrings zerlegt und die einzelnen Teilstücke in einem Array gespeichert werden, sind die gängigsten verwendeten PHP-Funktionen split(), preg_split() und explode(). Da split() und preg_split() im Gegensatz zu explode() mit regulären Ausdrücken arbeiten, ist zu erwarten, dass explode() die schnellste Variante ist. Das Beispiel-Script mit split() ist nur der Vollständigkeit halber …