I was in the middle of a code review a simple question came up: “What’s the fastest way to output a segmented string in PHP?”
echo '<div>'; echo '<span>'; echo 'This is a random number: ' . mt_rand(1,100); echo '</span>'; echo '</div>';
– OR –
$html = '<div>'; $html .= '<span>'; $html .= 'This is a random number: ' . mt_rand(1,100); $html .= '</span>'; $html .= '</div>'; echo $html;
My initial guess was that calling echo as little as possible during a request would end up performing better as there would be no need to interact with an output buffer or perform other logic tied to STDOUT
.
I ended up asking a few friends and colleges what they thought about the question and most responded with “hu?” After telling them that I was in fact serious the majority of their opinions fell on echo
being the winner. Still, others thought of ways to get a segmented string out faster, like pushing them onto an array and executing echo implode('', $array);
This difference of opinion got me thinking about what was truly the most efficient way to output a collection of strings? Curiosity got the best of me and I quickly setup some profiling tests using my Bench Class to find out the answer.
Profiling Setup
I used the following code in order to get enough data points for a solid performance comparison.
$samples = 40; $sets = array(10,20,50,100,500,1000,1500,2000,2500,3000); $results = array(); foreach($sets as $iterations) { $results[$iterations] = array(); for($i=0; $i<$samples; $i++) { Bench::start(); for($j=0;$j<$iterations;$j++) { // ... Output Test ... } $results[$iterations][] = Bench::stop(); Bench::reset(); } }
Output Tests
I tested the performance using four different methods of outputting data…
Echo
for($j=0;$j<$iterations;$j++) { echo 'abcdefghijklmnopqrstuvwxyz0123456789'; }
for($j=0;$j<$iterations;$j++) { print 'abcdefghijklmnopqrstuvwxyz0123456789'; }
Concatenation
$x = ''; for($j=0;$j<$iterations;$j++) { $x .= 'abcdefghijklmnopqrstuvwxyz0123456789'; } echo $x;
Array + Implode
$x = array(); for($j=0;$j<$iterations;$j++) { $x[] = 'abcdefghijklmnopqrstuvwxyz0123456789'; } echo implode('', $x);
Environment
I ended up testing with the php-cli in order to avoid the extra overhead of a browser and web server. When I attempted to test the performance in a browser it yielded vastly different datasets from one test to another.
Results
So this is what I ended up with…
Raw Numbers
10 | 20 | 50 | 100 | 500 | 1000 | 1500 | 2000 | 2500 | 3000 | |
---|---|---|---|---|---|---|---|---|---|---|
Concat | 3.80E-05 | 6.04E-05 | 0.0001506 | 0.0003327 | 0.0018855 | 0.0044077 | 0.0063608 | 0.0079579 | 0.0099115 | 0.0118193 |
Implode | 4.00E-05 | 6.05E-05 | 0.0001454 | 0.0003285 | 0.0017583 | 0.0040021 | 0.0059396 | 0.0081685 | 0.0106799 | 0.0131378 |
Echo | 2.43E-05 | 4.36E-05 | 0.0001046 | 0.0004600 | 0.0021742 | 0.0050115 | 0.006305 | 0.0086550 | 0.0105163 | 0.0133090 |
5.76E-05 | 0.000119 | 0.0002459 | 0.0006077 | 0.0026465 | 0.0048339 | 0.0065905 | 0.0086254 | 0.0109871 | 0.0130858 |
Graphs
Conclusions
As one can see there is very little difference in speed, and performance seems to scale up linearly. After playing around with various tested sizes I felt that going past the 3000 iterations mark would have been futile as it’s already quite a stretch that anyone would call echo that much within a single request.
While this post may be trivial it at least shows that there is no real performance benefits to using any of the four methods over one another. However, that’s not to say that all methods are equal when one is aiming towards maintainability – but that it another topic for a different day.
Summary
If you feel I’ve somehow misrepresented the data then by all means download the testing script, modify it, and educate me.
You can find the testing script and results here: PHP Output Profiling Testing Script.