Fastest Way To Match String With PHP

Thursday, July 10, 2008 - 09:35

There are many ways to find a string within another string using PHP, but which one is the quickest? I did the same sort of test that I have done with double or single quotes and downloading web pages with a few of the string matching functions available in PHP.

I first generated a very long string that could be used in the string matching functions. The following for loop generates a string containing "iteration 0 and iteration 1 and iteration 2..." right up until "iteration 4999 and".

1
2
3
4
$testString = '';
for ($i=0; $i < 5000; $i++) {
 $testString .= "iteration " . $i . " and ";
}

This was then passed to a number of string matching functions. This included the regular expression libraries contained in ereg() and preg_match(). The strpos() and strstr() functions were used as these are another common way of string matching, as well as some of their variants for matching case insensitive strings.

I created a loop that would go through all of these functions 10,000 times and search for the string "ation 1234", which was quite far into the string created in the loop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
for($i=0;$i<10000;$i++){
 $start = microtime();
 $y = ereg("ation 1234",$testString);
 $end = microtime();
 $results['ereg'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = eregi("ation 1234",$testString);
 $end = microtime();
 $results['eregi'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = eregi("ation 1234",$testString);
 $end = microtime();
 $results['eregi'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = preg_match("/ation 1234/",$testString);
 $end = microtime();
 $results['preg_match'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = preg_match("/ation 1234/i",$testString);
 $end = microtime();
 $results['preg_match_i'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = strstr($testString,"ation 1234");
 $end = microtime();
 $results['strstr'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = stristr($testString,"ation 1234");
 $end = microtime();
 $results['stristr'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = strpos($testString,"ation 1234");
 $end = microtime();
 $results['strpos'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = stripos($testString,"ation 1234");
 $end = microtime();
 $results['stripos'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = stripos($testString,"ation 1234");
 $end = microtime();
 $results['strrpos'][] = (getmicrotime($end) - getmicrotime($start));
 
 $start = microtime();
 $y = stripos($testString,"ation 1234");
 $end = microtime();
 $results['strripos'][] = (getmicrotime($end) - getmicrotime($start));
}

Here are the average times taken for each of the functions, in order of time taken.

1
2
3
4
5
6
7
8
9
10
0.0000303914 strpos
0.0000536556 strstr
0.0003520699 preg_match
0.0003982489 preg_match_i
0.0020656907 stristr
0.0021577688 stripos
0.0021580010 strripos
0.0021581690 strrpos
0.0025946639 ereg
0.0033165006 eregi

I tried the same thing again, but this time I used a string only 2 characters longer (one at each end) than the string being matched by the functions. Here are the average times taken, in order.

1
2
3
4
5
6
7
8
9
10
0.0000051508 strpos
0.0000052461 strstr
0.0000060365 strripos
0.0000060450 strrpos
0.0000060767 stripos
0.0000061181 stristr
0.0000064785 preg_match_i
0.0000067542 preg_match
0.0000117409 ereg
0.0000172299 eregi

This is kind of what I expected the result to be. The regular expression functions take longer because they have to load the necessary libraries before they can match the string. Also, using regular expressions has slightly more overhead than normal. What was interesting is that with a long string the preg_match() functions did better than many of the functions designed to look for strings. The fact that the ereg() functions are slower is of no surprise. In fact the php.net site has a note which states:

preg_match(), which uses a Perl-compatible regular expression syntax, is often a faster alternative to ereg().

All of these functions are very quick, but if you are really worried about performance then you should use the strpos() function to test for a string. Try to avoid using the special functions like strripos() unless you have a very small string. If the string is short then it is best no to use the regular expression functions unless you really need to.

Category: 
philipnorton42's picture

Philip Norton

Phil is the founder and administrator of #! code and is an IT professional working in the North West of the UK.
Google+ | Twitter

Comments

Good job with the test, it helped me redesign some code I was using for several projects. Though, its not surprising to find that the C/C++ method of string searching preforms better. Since, they are the closest to the machines' low level api's. Personally though I would still use the preg_*() api for more complex string parsing and templating. Also note that I cross referenced with phpbench.com

Good to know that preg_*s compare favourably to the string fnctions and there isn't a big overhead!

Thanks for doing the research.

Add new comment