Tom
Tom

Reputation: 1628

strpos vs preg_match - memory and resource differences

There have been questions asking which is faster strpos or preg_match, but I'm interested in knowing which uses the least memory and CPU resources.

I want to check a line for one of 5 matches:

if (strpos($key, 'matchA') !== false || strpos($key, 'matchB') !== false || strpos($key, 'matchC') !== false || strpos($key, 'matchD') !== false || strpos($key, 'matchE') !== false) 

if (preg_match("~(matchA|matchB|matchC|matchD|matchE)~i",$key, $match))

What is the best way to do this using the least strain on the server?

Upvotes: 0

Views: 654

Answers (2)

apokryfos
apokryfos

Reputation: 40730

I was curious so I wrote the following short script:

<?php

$keys = [
    "veryshort",
    "veryvertlongstringhereveryvertlongstringhereveryvertlongstringhereveryvertlongstringhereveryvertlongstringhereveryvertlongstringhere",
    "shortstringwithmatchBintheresomewhere",
    uniqid("",true).uniqid("",true).uniqid("",true).uniqid("",true).uniqid("",true).uniqid("",true).uniqid("",true).uniqid("",true).uniqid("",true) //just random stuff 
];
$ops = 1000000;

foreach ($keys as $key) {
    $mt = microtime(true);


    for ($i = 0;$i < $ops;$i++) {
        $bool = strpos($key, 'matchA') !== false || strpos($key, 'matchB') !== false || strpos($key, 'matchC') !== false || strpos($key, 'matchD') !== false || strpos($key, 'matchE') !== false;
    }

    $mtEnd = microtime(true);
    echo PHP_EOL."String $key".PHP_EOL;
    echo "StrPos".PHP_EOL;
    echo "Total time: ".($mtEnd-$mt).PHP_EOL;
    echo "Average time: ".($mtEnd-$mt)/$ops.PHP_EOL;

    $mt = microtime(true);
    for ($i = 0;$i < $ops;$i++) {
        $bool = preg_match("~(matchA|matchB|matchC|matchD|matchE)~i",$key, $match);
    }
    $mtEnd = microtime(true);
    echo "preg_match".PHP_EOL;
    echo "Total time: ".($mtEnd-$mt).PHP_EOL;
    echo "Average time: ".($mtEnd-$mt)/$ops.PHP_EOL;

}

This is the result I got.

String veryshort
StrPos
Total time: 0.4722261428833
Average time: 4.722261428833E-7
preg_match
Total time: 0.39836096763611
Average time: 3.9836096763611E-7

String veryvertlongstringhereveryvertlongstringhereveryvertlongstringhereveryvertlongstringhereveryvertlongstringhereveryvertlongstringhere
StrPos
Total time: 0.49143600463867
Average time: 4.9143600463867E-7
preg_match
Total time: 0.4594030380249
Average time: 4.594030380249E-7

String shortstringwithmatchBintheresomewhere
StrPos
Total time: 0.21032190322876
Average time: 2.1032190322876E-7
preg_match
Total time: 0.6224000453949
Average time: 6.224000453949E-7

String 577625b20d9632.50190056577625b20d9798.81879058577625b20d97e6.80533504577625b20d97f9.27988846577625b20d9806.94313293577625b20d9803.05317354577625b20d9818.68372474577625b20d9818.19126932577625b20d9825.80344644
StrPos
Total time: 0.50694704055786
Average time: 5.0694704055786E-7
preg_match
Total time: 0.4893159866333
Average time: 4.893159866333E-7

My interpretation on this is that running a single preg_match is faster than running multiple strpos because of function call overheads and additional comparisons per function, however, this does not seem to be the case when there is a match within your string, perhaps because when that happens the underlying regex state machine changes state and does more things (presumably).

I guess the answer is not as simple as "A is faster than B" but rather, "grab this code, put in your usual use cases in and see what's better for your particular case".

Upvotes: 1

Mav
Mav

Reputation: 1190

Jeffrey Friedl's Mastering Regular Expressions said that using the built in non-regex functions like strpos() and str_match() is always better and faster than using preg_match() (assuming you're using the preg suite) given that your match text is not a pattern.

Upvotes: 1

Related Questions