strpos vs preg_match - 内存和资源差异

strpos vs preg_match - memory and resource differences

有人问 strpospreg_match 哪个更快,但我想知道哪个使用的内存和 CPU 资源最少。

我想检查 5 个匹配项之一的一行:

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))

对服务器造成最小压力的最佳方法是什么?

Jeffrey Friedl 的 Mastering Regular Expressions 说使用 strpos()str_match() 等内置的非正则表达式函数总是比使用 preg_match() 更好更快(假设您正在使用preg 套件)鉴于您的 匹配文本不是模式

我很好奇,所以我写了以下简短的脚本:

<?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;

}

这是我得到的结果。

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

我对此的解释是 运行 单个 preg_match 比 运行 多个 strpos 快,因为函数调用开销和每个函数的额外比较,但是,当您的字符串中存在匹配项时,情况似乎并非如此,这可能是因为当发生这种情况时,底层正则表达式状态机会更改状态并执行更多操作(大概)。

我想答案不像 "A is faster than B" 那样简单,而是 "grab this code, put in your usual use cases in and see what's better for your particular case"。