Simple Machines Blogs > Developers' Blog

PHP String Replacement Speed Comparison

(1/6) > >>

Thantos:
Recently I redid a test to determine the speed of various string replacement methods in PHP.  A little over a year ago, Grudge did a test of the same nature.  Based off of his results some decisions were made on how to proceed.  My goal was to verify his test using some of the formats we decided to go with.

String Replacement Methods
I looked at the four main methods of string replacement used in SMF:

* sprintf
* preg_replace
* strtr
* str_replace
sprintf
http://www.php.net/manual/en/function.sprintf.php
sprintf operates almost exactly like the *printf functions in C.  Main difference is that PHP supports argument numbering.  We are slowly moving towards having all of our sprintfs using argument numbering.

preg_replace
http://www.php.net/manual/en/function.preg-replace.php
This function uses Perl regular expressions to find and replace substrings.  Regular Expressions can be extremely powerful and at the same time extremely hard to understand.

strtr
http://www.php.net/manual/en/function.strtr.php
strtr is used for translating one substring to another.  The way SMF has been using it is with the
--- Code: ---string strtr ( string $str, array $replace_pairs )
--- End code ---
format.  In this format, the longest substrings are found first and the function will try to avoid doing a replacement on something it has already worked on.

str_replace
http://www.php.net/manual/en/function.str-replace.php
str_replace finds substrings in the order they are given and replaces them with the corresponding substring.

Understanding the difference between strtr and str_replace
strtr and str_replace both seem to operate the same way.  However, due to strtr's unique properties the results can be very different.

Example:  PHP: Hypertext Preprocessor
Replacements:
   PHP => PHP: Hypertext Preprocessor
   PHP: Hypertext Preprocessor => PHP
strtr:      PHP
str_replace:   PHP: Hypertext Preprocessor

To understand why lets examine the behavior:

strtr
First strtr will sort the parameters by length of the substring with the longest first.  So we get
Replacements:
   PHP: Hypertext Preprocessor => PHP
   PHP => PHP: Hypertext Preprocessor

So it finds “ PHP: Hypertext Preprocessor” in our example and replaces it with “PHP” so now our example contains “PHP”.  Next it searches for “PHP” in “PHP” but the only instance it found is one it has already worked on so it doesn't do the replacement.  So it is done.

str_replace
First str_replace finds finds “PHP” in “PHP: Hypertext Preprocessor” and replaces it with “PHP: Hypertext Preprocessor” which gives us “PHP: Hypertext Preprocessor: Hypertext Preprocessor”.  Next it finds “PHP: Hypertext Preprocessor” in “PHP: Hypertext Preprocessor: Hypertext Preprocessor” which gives us “PHP: Hypertext Preprocessor” since it doesn't care that it already changed that part of the string.

Testing Procedure
A test script was written—attached to this post—and uploaded to the Simple Machines website.  The script was accessed and the results recorded throughout the day. The results will be more realistic on a production server then on a test server, due to the server load on production sites.  The times were varied in order to account for server load changes.

For each method the time was stored before and after the method was ran 100,000 times.  The difference in time was then calculated and displayed.

The str_replace method was ran using two different methods.  For the first method the parameters were put into arrays prior to starting the test.  For the second method the parameter arrays were created in every iteration.  This type of setup is typical and adds to the execution time.

Test Results
In the following table I give all the results of the each test.  The times for each method are in seconds.
Timesprintfpreg_replacestrtrstr_replace #1str_replace #208:00:00 AM1.13342.095548.14231.21091.481908:40:00 AM1.04362.032664.34921.79482.233711:30:00 AM1.18412.552462.01141.59311.920002:00:00 PM0.97832.483252.63391.39661.484503:00:00 PM1.04632.616452.78291.18281.4981Average1.07712.356055.98391.43571.7237
Calculated Results
The following table gives the speed of each method as a multiple of the time it took sprintf.
MethodTimes Slowerpreg_replace2.19strtr51.97str_replace #11.33str_replace #21.6Another method of comparing speeds is to look at the number of executions each method did each second.
MethodSpeedsprintf92838preg_replace42444strtr1786str_replace #169654str_replace #258016
Analysis of results
The sprintf method is the fastest in string replacement; however, str_replace method #1 was only slighty slower.

While the test were done over 100,000 iterations the actual number of replacements done during script execution shouldn't exceed more then a few hundred iterations.  As such, even strtr isn't too slow to be used.

It is also important to note that the preg_replace expression was very simplistic.  For more complex expressions the function will take longer to execute as pattern matching is not a simple problem.

My Recommendations
Whenever you are concerned with pure speed you should go with *printf.  However, when you are concerned about human readability str_replace provides a good alternative.  I recommend that you avoid using strtr unless you need its unique properties.  At the same time don't invest a lot of time trying to rip it out.



I hope you all gained some useful information for this.

Joshua Dickerson:
I remember doing a test a while back and receiving very different results. strtr() was the fastest out of the group. I might try your script out a little later and post my results.

I think it is important to note the PHP version, the webserver & version, the OS, the hardware, the load, and some specs relating to the software you are running. Since this is a benchmark of a core PHP function, I think the minimum that should be supplied is PHP version and the load.

Neverminding that stuff, nice to see some more benchmarks :). I loves me some benchmarks.

ディン1031:
Intressting, i new that strtr is slow... but so slow. I thought it depend on the array that you use for this.

Okay i prefere str_replace but i never thought that sprintf is so fast.

Bye
DIN1031

Thantos:

--- Quote --- strtr() was the fastest out of the group.
--- End quote ---
TBH I find that hard to believe.  strtr has much more work to do then str_replace does.  I can not see any reasonable implementation of str_replace being slower then strtr for the same set of replacements.  Well actually I could see one set of strings that it could be faster one, namely take a larger number of N substrings but the longest substring is the string S, then I could see strtr stopping at the first one but str_replace would still process the rest.  However that isn't really comparing speed and it plays off of strtr's properties.


--- Quote from: ディン1031 on June 05, 2007, 02:16:41 AM ---Intressting, i new that strtr is slow... but so slow. I thought it depend on the array that you use for this.

Okay i prefere str_replace but i never thought that sprintf is so fast.

Bye
DIN1031

--- End quote ---
When Grudge ran his test he used '%1$s' type of substrings for strtr and str_replace and in his results the strtr was much lower (though still slower then the rest).  I do suspect that the string lengths do play a role in the exact speed; but, for a typical set of strings I think the relationship between speeds will be about the same.

A good implementation of *printf only needs to scan the string once.  For str_replace I wouldn't be surprised if it scaned the string once for each substring.

Grudge:
Can you remember what my conclusions were out of interest?

Navigation

[0] Message Index

[#] Next page

Go to full version