Performance: preg_replace ist langsam!(?)
Dezember 4th, 2007 23:15 Uhr von
Ronald
Neulich habe ich ja schon die Auswirkungen von Konstanten mit Arrays in Bezug auf Speicherverbrauch verglichen. Nun ist es wieder Zeit für neue Performance-Erkenntnisse. Dieses Mal habe ich mir das Thema “preg_replace ist langsam!(?)” rausgesucht, da ich herausfinden wollte, wie “böse” wirklich die preg-Funktionen in Hinsicht auf Performance sind.
Mit preg-Funktionen muss man, wenn es denn geht, sparsam umgehen, sowas lernt man als PHP-Programmierer gleich von Anfang an. In der offiziellen PHP-Dokumentation steht es ja auch bei so ziemlich jeder preg-Funktion dabei, dass man sie nach Möglichkeit nicht nur für einfache Vergleiche (z.B. Ist String X in String Y enthalten) oder einfache Ersetzungen (z.B. ersetze “Hallo” mit “Auf Wiedersehen”) benutzen soll. Das ist auch richtig so, da die Funktionen mit den regulären Ausdrücken nun mal “gewichtiger” als die einfachen String-Funktionen (z.B. strpos, str_replace, etc.) sind. Aber inwiefern wirkt es sich auf die Laufzeit des Skripts aus? Ist jede Verwendung von preg_replace schon ein Performance-Killer? Ich habe mal ein paar Tests gemacht, die so sicherlich nicht auf den Alltag abzubilden sind, aber die Perfomance-Unterschiede auf gewisse Art darstellen sollen.
Zum Testen nehme ich zwei kurze Skripte, die, wie oben schon erwähnt, nicht sehr realitätsnah sind, aber hier ihren Zweck erfüllen. Skript Nummer 1 verwendet die Funktion preg_replace, Skript Nummer 2 gibt sich mit str_replace zufrieden.
Skript 1 – preg_replace
ini_set(“memory_limit”, “180M”);
$intTimeStart = time();
$intMax = 100;
$str = “Hallo %grausame% Welt”;
$str2 = “”;
for($i = 0; $i < $intMax; $i++) {
$str2 = preg_replace(“/%grausame%/i”, “schöne”, $str);
}
echo “\n\n“ . memory_get_peak_usage() / 1024 / 1024 . ” MB\n\n“;
echo “\n\n“ . time() – $intTimeStart . ” s\n\n“;
?>
Skript 2 – str_replace
ini_set(“memory_limit”, “180M”);
$intTimeStart = time();
$intMax = 100;
$str = “Hallo %grausame% Welt”;
$str2 = “”;
for($i = 0; $i < $intMax; $i++) {
$str2 = str_replace(“%grausame%”, “schöne”, $str);
}
echo “\n\n“ . memory_get_peak_usage() / 1024 / 1024 . ” MB\n\n“;
echo “\n\n“ . time() – $intTimeStart . ” s\n\n“;
?>
Die Variable $intMax stellt die Anzahl an “Ersetzungen” dar. Hier sind nun die Ergebnisse, wenn die Zahl entsprechend gesetzt wird.
$intMax = 100
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.0391 | 0 |
| str_replace | 0.0391 | 0 |
$intMax = 10000
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.0391 | 0 |
| str_replace | 0.0391 | 0 |
$intMax = 100000
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.0391 | 0 |
| str_replace | 0.0391 | 0 |
$intMax = 1000000
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.0391 | 2 |
| str_replace | 0.0391 | 2 |
$intMax = 10000000
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.0391 | 24 |
| str_replace | 0.0391 | 15 |
Interessante Ergebnisse! Da immer dieselben Strings behandelt werden, ist es nicht verwunderlich, dass der Speicherverbrauch immer gleich bleibt. Aber auch die Laufzeit ändert sich (bei diesem einfachen Beispielskript) erst ab einer (verdammt) hohen Anzahl an Funktionsaufrufen!
Hieraus kann man wohl erkennen, dass auch einfache preg_replace-Ersetzungen bei weitem nicht das ganze Skript ausbremsen. Dennoch ist es natürlich “guter Stil”, wenn man bei einfachen String-Operationen einen Bogen um die preg-Funktionen macht.
Nachtrag
Da war ich wohl etwas vorschnell!
Ich habe eben die Test noch mal wiederholt und dabei eine viel größere Zeichenkette genommen. Die Funktionen bleiben identisch, allerdings habe ich den Quelltext der Startseite von RVI-Media genommen und lasse nun zum Test alle div-Elemente durch span-Elemente ersetzen.
$intMax = 100
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.688 | 0 |
| str_replace | 0.664 | 0 |
$intMax = 1000
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.688 | 0 |
| str_replace | 0.664 | 1 |
$intMax = 100000
| Speicher in MB | Laufzeit in Sekunden | |
|---|---|---|
| preg_replace | 0.688 | 13 |
| str_replace | 0.664 | 6 |
Bei größeren Zeichenketten ist also schon bei weitaus weniger Durchläufen eine viel größere Diskrepanz zwischen den Funktionen zu spüren. Dennoch bleibt es dabei, dass es wirklich erst ab einer (sehr) großen Anzahl an Ersetzungen spürbar wird.
Geschrieben in PHP |
1 Kommentar »







Juni 2nd, 2010 um 19:54
Wow ein Benchmark ohne microtime.
Sachen wie 0 Sekunden im Vergleich zu 0 Sekunden oder 2 Sekunden zu 2 Sekunden sind wirklich sehr aufschlussreich!