My PHP Performance Benchmarks

PHP version 7.4.33 is running on this server.

Please note that these are micro benchmarks. Micro benchmarks are stupid. I created this comparison to learn something about PHP and how the PHP compiler works. This can not be used to compare PHP versions or servers.

Check if a String is empty

Method Undefined Null False Empty string String "0" String "1" Long string Summary Index
if ( ! $var )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms569
if (empty( $var) )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms238
if ( $var == "" )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms4 ms4 ms5226
if ( "" == $var )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms3 ms3 ms3599
if ( $var === "" )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms100
if ( "" === $var )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms101
if ( strcmp( $var, "" ) == 0 )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms370
if ( strcmp( "", $var ) == 0 )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms372
if ( strlen( $var ) == 0 )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms197
if ( ! strlen( $var ) )>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms>0 ms163

My conclusion: In most cases, use empty() because it does not trigger a warning when used with undefined variables. Note that empty( "0" ) returns true. Use strlen() if you want to detect "0". Try to avoid == at all because it may cause strange behaviour (e.g. "9a" == 9 returns true). Prefer === over == and !== over != if possible because it does compare the variable types in addition to the contents.

Compare two Strings

Method Equal First character not equal Last character not equal Summary Index
$a == $b>0 ms>0 ms>0 ms>0 ms100
!strcmp( $a, $b )>0 ms>0 ms>0 ms>0 ms251
strcmp( $a, $b ) == 0>0 ms>0 ms>0 ms>0 ms252
strcmp( $a, $b ) === 0>0 ms>0 ms>0 ms>0 ms254
strcasecmp( $a, $b ) === 0>0 ms>0 ms>0 ms1 ms446

My conclusion: Use what fits your needs.

Check if a String contains another String

Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74 Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74 Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74 Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74 Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74 Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74 Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74 Warning: Division by zero in /www/htdocs/w0079121/test/php-performance/index.php on line 74
Method Not found Found at the start Found in the middle Found at the end Summary Index
strstr( $haystack, $needle )>0 ms>0 ms>0 ms>0 ms>0 ms0
strpos( $haystack, $needle ) !== FALSE>0 ms>0 ms>0 ms>0 ms>0 ms0
strstr( $haystack, $needle ) !== FALSE>0 ms>0 ms>0 ms>0 ms>0 ms0
stristr( $haystack, $needle )>0 ms>0 ms>0 ms>0 ms1 ms0
preg_match( "/$needle/", $haystack )>0 ms>0 ms>0 ms>0 ms>0 ms0
preg_match( "/$needle/i", $haystack )>0 ms>0 ms>0 ms>0 ms>0 ms0
preg_match( "/$needle/S", $haystack )>0 ms>0 ms>0 ms>0 ms>0 ms0
Function ereg is deprecated since 5.30 ms0 ms0 ms0 ms0 ms0

My conclusion: It does not matter if you use strstr() or strpos(). Use the preg…() functions only if you need the power of regular expressions. Never use the ereg…() functions.

Check if a String starts with another String

Method Not found Found at the start Found in the middle Found at the end Summary Index
strncmp( $haystack, $needle, strlen( $needle ) ) === 0>0 ms>0 ms>0 ms>0 ms>0 ms113
strncmp( $haystack, $needle, 4 ) === 0>0 ms>0 ms>0 ms>0 ms>0 ms100
strncasecmp( $haystack, $needle, strlen( $needle ) ) === 0>0 ms>0 ms>0 ms>0 ms>0 ms111
strpos( $haystack, $needle ) === 0>0 ms>0 ms>0 ms>0 ms>0 ms108
substr( $haystack, 0, strlen( $needle ) ) === $needle>0 ms>0 ms>0 ms>0 ms>0 ms126
strcmp( substr( $haystack, 0, strlen( $needle ) ), $needle ) === 0>0 ms>0 ms>0 ms>0 ms>0 ms185
preg_match( "/^" . preg_quote( $needle, "/" ) . "/", $haystack )>0 ms>0 ms>0 ms>0 ms1 ms395

My conclusion: strpos() is very fast and can be used in almost all cases. strncmp() is good if you are looking for a constant length needle.

Check if a String ends with another String

Method Not found Found at the start Found in the middle Found at the end Summary Index
substr( $haystack, strlen( $haystack ) - strlen( $needle) ) === $needle>0 ms>0 ms>0 ms>0 ms>0 ms105
substr( $haystack, -strlen( $needle) ) === $needle>0 ms>0 ms>0 ms>0 ms>0 ms100
strcmp( substr( $haystack, - strlen( $needle) ), $needle) === 0>0 ms>0 ms>0 ms>0 ms>0 ms146
preg_match( "/" . preg_quote( $needle, "/" ) . "$/", $haystack )>0 ms>0 ms>0 ms>0 ms1 ms346

My conclusion: Using substr() with a negative position is a good trick.

Replace a String inside another String

Method Not found Found at the start Found in the middle Found at the end Summary Index
str_replace( $search, $replace, $subject )>0 ms>0 ms>0 ms>0 ms>0 ms28975
preg_replace( "/$search/", $replace, $subject )>0 ms>0 ms>0 ms>0 ms>0 ms49150
preg_replace( "/$search/S", $replace, $subject )>0 ms>0 ms>0 ms>0 ms>0 ms49150
Function ereg_replace is deprecated since 5.30 ms0 ms>0 ms0 ms>0 ms100

My conclusion: Never use the ereg…() functions.

Trim Characters from the Beginning and End of a String

Method Not found Found at start Found at end Found at both sides Summary Index
trim( $string, "," )>0 ms>0 ms>0 ms>0 ms>0 ms100
preg_replace( '/^,*|,*$/', "", $string )>0 ms>0 ms>0 ms>0 ms1 ms3383
preg_replace( '/^,*|,*$/m', "", $string )1 ms1 ms1 ms1 ms4 ms22101
preg_replace( '/^,+|,+$/', "", $string )>0 ms>0 ms>0 ms>0 ms>0 ms291
preg_replace( '/^,+|,+$/m', "", $string )>0 ms>0 ms>0 ms>0 ms>0 ms316
preg_replace( '/^,+/', "", preg_replace( '/,+$/', "", … ) )>0 ms>0 ms>0 ms>0 ms>0 ms469

My conclusion: Always benchmark your regular expressions! In this case, with .* you also replace nothing with nothing which takes time because there is a lot of “nothing” in every string.

Split a String into an Array

Method Empty string Single occurrence Multiple occurrences Summary Index
explode( ",", $string )>0 ms>0 ms1 ms1 ms76175
Function split is deprecated since 5.30 ms0 ms>0 ms>0 ms100
preg_split( "/,/", $string )>0 ms>0 ms1 ms1 ms94825
preg_match_all( '/[^,]+/', $string, $matches )>0 ms>0 ms1 ms1 ms145425

My conclusion: Don't use split(). It's deprecated in PHP 5.3 and will be removed in PHP 6.

Loop a numerical indexed Array of Strings

Method Summary Index
for ( $i = 0; $i < count( $array ; $i++ )>0 ms170
for ( $i = 0, $count = count( $array ); $i < $count; $i++ )>0 ms100
for ( $i = count( $array ) - 1; $i >= 0; $i-- )>0 ms109
for ( $i = count( $array ) - 1; $i >= 0; --$i )>0 ms108
$i = count( $array ); while ( $i-- )>0 ms132

My conclusion: count() is horribly slow. Always precalculate it, if possible.

Get Elements from an Array

Method Summary Index
$array[0]1 ms101
$array['key']1 ms100

My conclusion: I like associative arrays.

Implode an Array

Method Summary Index
implode( " ", $array )>0 ms104
"$array[0] $array[1] $array[2]">0 ms103
$array[0] . " " . $array[1] . " " . $array[2]>0 ms100
sprintf( "%s %s %s", $array[0], $array[1], $array[2] )>0 ms1729
vsprintf( "%s %s %s", $array )>0 ms1713

My conclusion: String concatenation is a cheap operation in PHP. Don't waste your time benchmarking this.

The single vs. double Quotes Myth

Method Summary Index
'contains no dollar signs'>0 ms100
"contains no dollar signs">0 ms108
'$variables $are $not $replaced'>0 ms100
"\$variables \$are \$not \$replaced">0 ms108
"$variables $are $replaced">0 ms110
$variables . ' ' . $are . ' ' . $replaced>0 ms108
$variables . " " . $are . " " . $replaced>0 ms100

My conclusion: It does not matter if you use single or double quotes at all. The inclusion of variables has a measurable effect, but that's independent from the quotes.