So, aus gegebenen Anlass, möchte ich euch das Thema Geschwindigkeit in PHP näher bringen.
Das Ganze begann am Wochenende mit einer Diskussion zwischen meinem Bruder und mir mit dem Thema "Performance und Syntax von PHP". Es ist wohl klar, dass PHP in Sachen Geschwindigkeit nicht mit den Kontrahenten ASP.NET, JSP oder Python mithalten kann. PHP ist nun mal eine interpretierte Sprache und bietet damit nur eine relativ dürftige Performance.
Das musste ich gestern in der Arbeit hart zu spüren bekommen. Ich entwickelte eine Suchfunktion für das aktuelle Projekt. Die Seite hat etwas mehr und größere Unterseiten und ich wollte keinen heuristischen Algorithmus entwickeln, sondern möglichst gute Ergebnisse geliefert bekommen. Außerdem sollte die Suche auf aktuelle Daten und nicht auf Indizes zugreifen.
Das Ergebnis konnte sich sehen lassen: Tests ergaben die Ergebnisse, die wirklich perfekt passten. Doch das große Manko: Weil Tag-Clouds, Meta-Tags, Überschriften und Texte und Alternativtexte von Bildern einzeln gewichtet werden und deshalb einzeln geparst werden; weil passende Stücke aus durchaus großen Seiten herausgepickt werden (mit konfigurierbarer Länge); und weil Treffer visuell in den Abschnitten hervorgehoben werden - dauerte die Suche bei einer Stichwortsuche mit drei Begriffen in etwa drei Sekunden - Viel zu lange, für eine Suchfunktion einer Website!
Deshalb habe ich mich etwas mit Geschwindigkeitsoptimierung von PHP-Scripten beschäftigt. Und siehe da: Ein paar kleine Änderungen hier und da: Qualitativ gleichbleibende Ergebnisse mit etwa einer Sekunde Laufzeit.
Die wichtigsten 20 Punkte im Bereich PHP-Geschwindigkeitsoptimierung möchte ich euch im Folgenden präsentieren.
Viele haben erst Auswirkungen, bei vielen Schleifendurchläufen oder langen Texten, doch alle haben einen Effekt - wie man an meinem Script sieht.
------------------------------------
01. "Hallo ".$world; ist schneller als "Hello $world";. Das kommt daher, weil PHP beim parsen eines Strings
viele Zeichen überprüfen muss. Durch das beenden des Strings vor dem Anketten einer Variable lässt PHP in einen dementsprechend schnelleren Modus umspringen.
02. ' ist schneller als ". Dies hat einen ähnlichen Grund viel der vorherige Punkt. Bei " müssen einfach viel mehr steuerzeichen überprüft werden, als bei ', wo PHP mehr oder minder einfach drüberfährt.
03. file_get_contents() und file_put_contents() ist schneller, als andere Methoden, um Dateien zu lesen. Die kommt ganz klar daher, dass PHP intern einfach keine Arrays oder ähnliches konstruieren muss.
04. strpos() ist schneller als preg_match() - preg_match() ist schneller als ereg() - Auch die entsprechenden Replace-Funktionen. Das sollte auch jedem klar sein sein, warum. Deshalb immer vereinfachen versuchen.
05. Bei zu speichernden Daten viel beim Eintragen rechnen. Auslesen kommt öfter vor. Wenn ihr etwa in Datenbanken, Dateien, o.Ä. eintragt, rechnet eher beim Eintragen. Wenn der Eintrag zehn mal ausgelesen wird, erspart ihr euch auch zehn Rechenzyklen.
06. Wenn möglich, den Output zusammenfassen und auf einmal ausgeben. Die kommt daher, weil echo & Co. mit Datenverkehr verbunden wird. Das erklärt auch den häufigen header()-Fehler. Ein Template-System kann da viel helfen.
07. PHP-Tags schließen, wenn ein langer Text ausgegeben wird. Bevor man mit echo einen langen Text, wie zum Beispiel den Grundaufbau der Seite ausgibt, sollte man eher mit ?> den PHP-Code beenden und auf "Inline-PHP" zugreifen.
08. Output-Buffering und GZip-Kompression verwenden (falls möglich) ob_start() ist eine der nützlichsten funktionen in diesem Bereich. Hier wird jeglicher Output zwischengespeichert und kann anschließend, ähnlich einem Template-System verabreitet werden. Auch GZip-komprimierte Datenübertragungen können viel Geschwindigkeit bringen.
09. OOP vermeiden. OOP ist eine grandiose Erfindung. Aber nicht für PHP. PHP ist und bleibt eine interpretierte Sprache. Und jede Klasse muss zuerst geparst werden. Außerdem dauert der Zugriff auf Elemente einer Klasse vier mal länger, als auch normale Variablen.
10. Beim komplexen Algorithmen Schleifendurchgänge zusammenfassen. Falls ihr schon eine etwas komplexere Funktion mit vielen Schleifen geschrieben habt, werdet ihr die Gecshwindigkeit-Lecks von PHP sicher auch schon gesehen haben. Hier hilft es oft Schleifendurchgänge zusammenzufassen und Ausnahmekriterien (wie ersten und letztes Element) explizit zu behandeln. So fällt die überprüfung weg.
11. Auch mal Heuristiken verwenden. Ein Algorithmus muss nicht immer perfekte Ergebnisse liefern. Gute reichen oft auch. Durch einen einfachen Denkanstoß, kann eine Heuristik große Geschwindigkeitsscüber bringen.
12. Viel in den Speicher laden und auf Variablen zurückgreifen, nicht auf Funktionsaufrufe. Wenn ihr die Länge ienes String zehn mal bestimmen müsst, berechnet sie einmal und speichert sie in einer Variable. Zehn mal strlen() benötigt auch eine entsprechend höhere Laufzeit.
13. Keine gleichbleibenden Berechnungen in Schleifen lassen, sondern vor die Schleife setzen. Niemals eine Schleife in der Form "for($i = 0; $i < count($array_a); $i++)" implementieren. Bei jedem Schleifendurchgang wird die mittlere Bedingung geprüft. Lieber vor der Schleife in eine Variable schreiben. Das gilt auch für Berechnungen innerhalb der Schleife, die in jedem Durchgang dasselbe Ergebnis liefern.
14. Möglichst simple Variablen-Typen an Unterprogramme übergeben. Arrays und Objekte benötigen viel Rechenzeit. Deshab lieber die gewünschten Werte beim Aufruf auslesen und einzeln übergeben.
15. Objekte und Arrays als Referenzen übergeben. Wenn es wirklich notwendig ist, Arrays und Objekte an Unterprogramme zu übergeben, tut dies per & und macht sie zu Referenzen. PHP kann darauf schneller zugreifen.
16. Nicht mehr gebrauchte Arrays und Objekte per unset() löschen. Gerade diese großen Variablentypen benötigen viel Speicher. Wer sich schon mal mit dem Speicheraufbau eines Prozessors beschäftigt hat, wird mir zustimmen, dass das freigeben großer Bereiche Leben retten kann.
17. Möglichst wenig Funtkionsaufrufe, wenn sie nicht unbedingt notwendig sind. Jeder Funktonsaufruf benötigt mehr Zeit, als eine normale Iteration. Deshalb lieber mal Code zwei oder drei mal kopieren, anstatt unnötige Unterprogrammaufrufe zu starten.
18. Datenbanken sollten unbedingt indiziert werden. Das betrifft zwar nicht direkt PHP, aber viele Anwendungsbereiche PHPs. MySQL & Co. bekommen einen enormen GEschwindigkeitsschub durch einen Index.
19. Zend bietet einen PHP Optimizer an, der das Laden und Interpretieren bis zu doppelt so schnell machen kann. Erklärt sich glaub ich von selbst ;D
20. Webserveroptimierung: Das größte Optimierungspotential steckt jedoch im Server. Wie man diese genau konfigurieren sollte, könnt ihr hier nachlesen: http://phplens.com/lens/php-book/…bugging-php.php
------------------------------------
Ich hoffe, ich konnte euch das Thema "Geschwindigkeit und PHP" etwas näher bringen. Ich wünsche euch viel Glück bei großen Projekten. Eure Benutzer werden euch kurze Rechenzeiten danken
Bei meinem Script wurden vor Allem folgende Punkte implementiert: 01, 02, 03, 04, 06, 09, 10 (!), 12, 13, 14 15, 17.
Liebe Grüße
Dodo