Friday, March 28, 2014

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

1 comment:


  1. You have provided an nice article, Thank you very much for this one. And i hope this will be useful for many people.. and i am waiting for your next post keep on updating these kinds of knowledgeable things...

    Android App Development Company

    ReplyDelete

Labels

performance (23) benchmark (6) MySQL (5) architecture (5) coding style (5) memory usage (5) HHVM (4) C++ (3) Java (3) Javascript (3) MVC (3) SQL (3) abstraction layer (3) framework (3) maintenance (3) Go (2) Golang (2) HTML5 (2) ORM (2) PDF (2) Slim (2) Symfony (2) Zend Framework (2) Zephir (2) firewall (2) log files (2) loops (2) quality (2) real-time (2) scrum (2) streaming (2) AOP (1) Apache (1) Arrays (1) C (1) DDoS (1) Deployment (1) DoS (1) Dropbox (1) HTML to PDF (1) HipHop (1) OCR (1) OOP (1) Objects (1) PDO (1) PHP extension (1) PhantomJS (1) SPL (1) SQLite (1) Server-Sent Events (1) Silex (1) Smarty (1) SplFixedArray (1) Unicode (1) V8 (1) analytics (1) annotations (1) apc (1) archiving (1) autoloading (1) awk (1) caching (1) code quality (1) column store (1) common mistakes (1) configuration (1) controller (1) decisions (1) design patterns (1) disk space (1) dynamic routing (1) file cache (1) garbage collector (1) good developer (1) html2pdf (1) internationalization (1) invoice (1) just-in-time compiler (1) kiss (1) knockd (1) legacy code (1) legacy systems (1) logtop (1) memcache (1) memcached (1) micro framework (1) ncat (1) node.js (1) openssh (1) pfff (1) php7 (1) phpng (1) procedure models (1) ramdisk (1) recursion (1) refactoring (1) references (1) regular expressions (1) search (1) security (1) sgrep (1) shm (1) sorting (1) spatch (1) ssh (1) strange behavior (1) swig (1) template engine (1) threads (1) translation (1) ubuntu (1) ufw (1) web server (1) whois (1)