PHP-Performance: preg_match vs. strpos

Folgendes Problem hat man als Coder sicherlich öfters zu lösen: Man möchte wissen ob String A, String B oder String C (u.s.w) in einem Text vorkommen. Beispielsweise holt man eine Liste mit Keywords aus einer Datenbank und möchte wissen ob eins dieser Keywords in einem Text vorkommt.
Um das Problem zu lösen gibt es sicherlich zig verschiedene Möglichkeiten. Die gängigsten sehen wahrscheinlich in etwas so aus:

if(stripos($haystack, $needle) !== false)
{
	$found = true;
}
if(preg_match('/'.$needle.'/is', $haystack) == 1)
{
	$found = true;
}


Hierbei wird eine Sache schnell klar: Bei mehr als einem Suchsting wird das ganze etwas komplizierter. Man muss die strpos Variante für jeden Suchstring einmal laufen lassen, bzw. in der zweiten Variante die Suchstrings mit einem oder verknüpfen.
Die Frage ist nun: Welche der beiden Varianten ist schneller?

Ich habe ein kurzes Testscript gebastelt, und hier ist das Ergebnis:
performance_preg_match performance_strpos

Die preg_match Varinate ist um einiges schneller. Ausserdem fällt auf das bei 10000 Durchläufen des Testscript die Funktion stripos öfter als 10000 mal ausgeführt wird. Die liegt daran, dass die Funktion so oft aufgerufen werden muss, bis der erste Suchstring gefunden wurde (oder eben keiner der gesuchten Strings im Text vorkommt). Durch die oder-Verknüpfung der einzelnen Strings muss preg_match bei jedem Durchlauf nur einmal ausgeführt werden.
Klar wird also: Je mehr Suchstrings in einem Text gesucht werden sollen, desto langsamer wird die strpos Variante im Vergleich zu preg_match, obwohl natürlich auch der reguläre Ausdruck bei einem längeren Suchstring etwas langsamer wird.

Zum Schluss noch das Script mit dem ich dieses Verhalten getestet habe:
performance_preg_vs_strpos.php

2 thoughts on “PHP-Performance: preg_match vs. strpos

  1. Günter

    achja stimmt, den Test wolltest du ja auch noch liefern…

    Sehr interessanter versuch, tatsächlich ist preg* nicht so langsam wie alle immer behaupten, vor allem nicht bei komplexere “needles”…

  2. Thomas

    Bei einfachen Suchvergleichen (also einfacher Test ob Zeichenkette enthalten ist) ist bei meinem Test die Funktion strstr der Gewinner.

    Testergebnisse bei 10000 durchläufe:
    strstr:0.057003021240234
    stripos:0.065004110336304
    preg_match:0.080003976821899

    Test, Suchstring Zeichenkette %field%:

    <?php
    $mtstart = microtime(true);
    for ($i = 0; $i < 10000; $i++)
    {
    strstr('abc%field%abc', '%field%');
    }
    $mtende = microtime(true);
    echo 'strstr:'.($mtende-$mtstart).'';

    $mtstart = microtime(true);
    for ($i = 0; $i < 10000; $i++)
    {
    stripos('abc%field%abc', '%field%');
    }
    $mtende = microtime(true);
    echo 'stripos:'.($mtende-$mtstart).'';

    $mtstart = microtime(true);
    for ($i = 0; $i < 10000; $i++)
    {
    preg_match('(\%field\%)', 'abc%field%abc') === 1;
    }
    $mtende = microtime(true);
    echo 'preg_match:'.($mtende-$mtstart).'';
    ?>

Leave a Reply

Your email address will not be published. Required fields are marked *

π