strpos() vs. preg_match() vs. stripos()

Lessons learned:
  • strpos() is 3-16 times faster than preg_match()
  • stripos() is 2-30 times slower than strpos()
  • stripos() is 20-100 percent faster than preg_match() with the caseless modifier "//i"
  • using a regular expression in preg_match() is not faster than using a long string
  • using the utf8 modifier "//u" in preg_match() makes it 2 times slower

Here is a sample script to compare the functions with different string sizes:

<?php

function loop(){

$str_50 = str_repeat('a', 50).str_repeat('b', 50);
$str_100 = str_repeat('a', 100).str_repeat('b', 100);
$str_500 = str_repeat('a', 250).str_repeat('b', 250);
$str_1k = str_repeat('a', 1024).str_repeat('b', 1024);
$str_10k = str_repeat('a', 10240).str_repeat('b', 1024);
$str_100k = str_repeat('a', 102400).str_repeat('b', 1024);
$str_500k = str_repeat('a', 1024*500).str_repeat('b', 1024);
$str_1m = str_repeat('a', 1024*1024).str_repeat('b', 1024);

$b = 'b';
$b_10 = str_repeat('b', 10);
$b_100 = str_repeat('b', 100);
$b_1k = str_repeat('b', 1024);

echo str_replace(',', "\t", ',strpos,preg,preg U,preg S,preg regex,stripos,preg u,'.
'preg i,preg u i,preg i regex,stripos uc,preg i uc,preg i uc regex').PHP_EOL;

foreach (array($b, $b_10, $b_100, $b_1k) as $needle) {
foreach (array($str_50, $str_100, $str_500, $str_1k, $str_10k,
$str_100k, $str_500k, $str_1m) as $str) {

echo strlen($needle).'/'.strlen($str);

$start = mt();
for ($i=0; $i<25000; $i++) $j = strpos($str, $needle); // strpos
echo "\t".mt($start);

$regex = '!'.$needle.'!';
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg
echo "\t".mt($start);

$regex = '!'.$needle.'!U';
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg Ungreedy
echo "\t".mt($start);

$regex = '!'.$needle.'!S';
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg extra analysiS
echo "\t".mt($start);

$regex = "!b{".strlen($needle)."}!";
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg regex
echo "\t".mt($start);

$start = mt();
for ($i=0; $i<25000; $i++) $j = stripos($str, $needle); // stripos
echo "\t".mt($start);

$regex = '!'.$needle.'!u';
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg utf-8
echo "\t".mt($start);

$regex = '!'.$needle.'!i';
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg i
echo "\t".mt($start);

$regex = '!'.$needle.'!ui';
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg i utf-8
echo "\t".mt($start);

$regex = "!b{".strlen($needle)."}!i";
$start = mt();
for ($i=0; $i<25000; $i++) $j = preg_match($regex, $str); // preg i regex
echo "\t".mt($start);

echo PHP_EOL;
}
echo PHP_EOL;
}
}

function mt($start=null){
if ($start === null) return microtime(true);
return number_format(microtime(true)-$start, 4);
}

loop();

Running with PHP 5.4.4, 64bit, 2.3GHz (QEMU):
strpospregpreg Upreg S preg regexstripospreg upreg i  preg u i preg i regex
1/1000.00520.01440.01470.01720.01680.01020.01800.01530.01950.0143
1/2000.00580.01770.01660.01590.01430.01210.02290.01600.02360.0159
1/5000.00610.02370.02460.02360.02190.02150.03940.02170.03830.0212
1/20480.00870.05890.05900.05800.03590.06450.12050.04990.10770.0472
1/112640.02210.26930.26720.26400.24430.31150.59390.36310.68030.3662
1/1034240.18672.34322.33842.35752.32112.93275.30403.46896.43913.4750
1/5130241.022811.400611.353012.068911.385814.502326.070117.265831.654316.9941
1/10496002.098823.356123.338223.381123.445930.211952.993734.965464.414135.1033
10/1000.00550.01670.01710.01660.01480.01040.01990.01580.02150.0150
10/2000.00530.01650.01550.01800.01510.01250.02220.01670.02640.0175
10/5000.00650.02470.02260.02190.01790.02070.03910.02220.03760.0236
10/20480.00880.05900.05780.06250.03710.06490.11920.05030.11080.0484
10/112640.02120.27010.26520.26170.24120.30680.58380.35530.66520.3491
10/1034240.15422.32742.29722.29382.27652.75865.17893.40966.31193.3939
10/5130240.723611.438811.488011.493211.331214.185125.792717.138832.190217.5287
10/10496001.495123.407223.200023.417523.243929.679453.052634.964164.986135.9626
100/1000.00630.19630.19560.01860.12640.01460.29220.20610.22810.1397
100/2000.00600.02340.02190.02190.02120.01800.02960.03090.04220.0235
100/5000.00710.03040.02970.02910.02500.02730.04520.03760.05590.0310
100/20480.01030.06710.06810.06760.04280.07620.13290.06650.12390.0516
100/112640.02100.26250.26230.26420.24220.30670.57620.36000.67740.3548
100/1034240.14742.28642.28562.31142.29682.78585.22613.45066.32823.4003
100/5130240.724111.405411.428611.343511.531314.150725.688517.170231.819517.1162
100/10496001.473623.225823.472423.259523.305229.427653.405135.201564.381834.6691
1024/1000.00470.20330.20410.05170.10420.00830.28990.20920.22900.1204
1024/2000.00490.05620.05540.05630.29000.01090.06150.53400.64960.3281
1024/5000.00490.06470.06380.06371.33580.01810.07612.50633.28111.4076
1024/20480.00690.09550.09540.09630.06880.08870.15260.15360.23670.0809
1024/112640.01950.29740.29820.30000.28170.33750.61680.47180.81030.3845
1024/1034240.15242.33562.33162.34772.33382.83515.27273.55356.47033.4583
1024/5130240.721711.428311.537711.498711.416214.286225.813117.176233.163318.1542
1024/10496001.465723.327223.220523.275223.681229.180454.996234.972064.752937.1609

Running with HHVM 3.0/2014.03.27, 64bit, 2.3GHz (QEMU):
strpospregpreg Upreg S preg regexstripospreg upreg i  preg u i preg i regex
1/1000.00280.00810.00850.00790.00790.00390.01240.00840.01250.0085
1/2000.00210.00930.00940.00920.00940.00450.01670.00910.01620.0088
1/5000.00210.01600.01830.01680.01210.01020.03410.01540.03090.0138
1/20480.00510.05410.05310.05230.03020.03740.11180.03960.09800.0394
1/112640.01760.25310.25370.25410.23730.34150.56820.34510.66020.3436
1/1034240.17812.29552.28462.28142.25353.38805.21393.37446.27483.4123
1/5130241.042511.347711.665311.414911.301816.922726.714217.259531.654117.2308
1/10496002.124123.263523.252523.305423.225634.950852.701234.902464.522134.9430
10/1000.00130.00840.00840.00860.00760.00400.01260.00860.01190.0077
10/2000.00140.00890.00910.00910.00880.00630.01580.01080.01670.0095
10/5000.00200.01550.01580.01570.01200.01290.03080.01560.03080.0147
10/20480.00730.05000.04960.05050.02950.04770.10880.04100.10320.0397
10/112640.01690.25360.25220.25190.23120.45720.56680.34980.66140.3443
10/1034240.18292.31302.29262.30032.28264.55265.23293.45116.42433.4623
10/5130241.061011.535811.524811.494811.419822.937225.916517.067431.421416.9746
10/10496002.078323.813123.731923.198823.209846.539853.548035.472865.456135.6284
100/1000.00120.00650.00620.00660.00580.00170.01120.00660.01010.0059
100/2000.00130.01020.01010.01030.01180.01060.01720.01730.02500.0126
100/5000.00180.01650.01630.01660.01490.01700.03200.02190.03830.0176
100/20480.00420.05050.05030.05080.03180.05100.10900.04730.10850.0432
100/112640.01780.25560.25350.25520.23560.46050.56900.35370.68250.3559
100/1034240.17642.29922.30042.29662.28814.55225.19243.43466.29673.4354
100/5130241.029611.365711.377611.304611.412522.588926.007116.988632.371016.9588
100/10496002.106423.423923.323623.217423.192946.475653.412934.854265.245735.4284
1024/1000.00130.01160.01170.01210.00600.00090.02160.01220.01540.0058
1024/2000.00090.01510.01510.01540.00710.00090.02790.01390.02010.0074
1024/5000.00090.02160.02160.02190.01040.00090.04260.01900.03310.0132
1024/20480.00300.05570.05560.05620.06320.09390.11970.11730.19470.0742
1024/112640.01610.26240.25900.25880.26590.49810.57890.41640.75760.3794
1024/1034240.14672.29022.31722.29942.28574.56485.21193.47266.36263.4485
1024/5130240.716011.387111.434511.303411.456122.756125.856417.033331.401416.9700
1024/10496001.486423.177123.103323.414323.336447.551355.756136.790064.784635.1457

0 comments:

Post a Comment