How you write your String matters: benchmarking PHP
Testing how different types of string specification compare in terms of execution speed in PHP
There are a lot of ways in which you can specify, use and print string in PHP. They all have different benefits and drawbacks and that's not the content of this article. The focus of these tests is to determine how using different string specifications affects the performances of your PHP code.
TL;DR: Single quoted strings are the most performing, both for simple text and for concatenation with other variables.
Tests
Compared 3 types of string specification:
- Single Quoted (e.g.
echo 'string';
) - Double Quoted (e.g.
echo "string";
) - HEREDOC (e.g.
echo <<<EOT string EOT;
)
For each type of specification, 2 tests:
- Simple string (e.g.
'string'
) - String + a variable (e.g.
'string'.$var
)
Iterations
In order to simulate a strong workload and have more data, the code ran 10 iterations with a 5-second pause. For each iteration 1 Million echo
were executed, without any pause.
To make sure that the machine load doesn't skew the results, all the 3 different specifications are executed within the same iteration, one after the other, with the same 5-second delay. So at any point in time, the load should be equally distributed among the different specifications.
Buffer
Since the actual printing of the strings must not affect these tests, ob_start()
and ob_end_clean()
are used to not print anything, and ob_clean()
is used within each iteration to free up the buffer.
The Code
This is the code used to run the tests.
<?php
define('MAX_PER_ITERATION', 10000000);
define('MAX_ITERATIONS', 10);
define('SLEEP_TIME', 5);
echo "TEST 1: Simple String\n";
$times = [
'quote' => [],
'doublequote' => [],
'heredoc' => []
];
for ($k = 1; $k <= MAX_ITERATIONS; $k++) {
echo "Iteration ".$k."\n";
/* Start Single Quote tests */
echo "\tQuote\n";
ob_start();
$start = microtime(true);
for ($i = 0; $i < MAX_PER_ITERATION; $i++) {
echo 'string';
ob_clean();
}
$diff = (microtime(true) - $start);
ob_end_clean();
$times['quote'][] = $diff;
sleep(SLEEP_TIME);
/* Start Double Quote tests */
echo "\tDouble Quote\n";
ob_start();
$start = microtime(true);
for ($i = 0; $i < MAX_PER_ITERATION; $i++) {
echo "string";
ob_clean();
}
$diff = (microtime(true) - $start);
ob_end_clean();
$times['doublequote'][] = $diff;
sleep(SLEEP_TIME);
/* Start HEREDOC tests */
echo "\tHeredoc\n";
ob_start();
$start = microtime(true);
for ($i = 0; $i < MAX_PER_ITERATION; $i++) {
echo <<< EOT
string
EOT;
ob_clean();
}
$diff = (microtime(true) - $start);
ob_end_clean();
$times['heredoc'][] = $diff;
sleep(SLEEP_TIME);
}
foreach ($times as $type => $results) {
echo $type."\n";
foreach ($results as $r) {
echo "\t\t".$r."\n";
}
$avg = array_sum($results) / sizeof($results);
echo "\tAvg: ".$avg."\n";
}
sleep(100);
echo "TEST 2: String with Variable\n";
$times = [
'quote' => [],
'doublequote' => [],
'heredoc' => []
];
$variable = 'string2';
for ($k = 1; $k <= MAX_ITERATIONS; $k++) {
echo "Iteration ".$k."\n";
/* Start Single Quote tests */
echo "\tQuote\n";
ob_start();
$start = microtime(true);
for ($i = 0; $i < MAX_PER_ITERATION; $i++) {
echo 'string'.$variable;
ob_clean();
}
$diff = (microtime(true) - $start);
ob_end_clean();
$times['quote'][] = $diff;
sleep(SLEEP_TIME);
/* Start Double Quote tests */
echo "\tDouble Quote\n";
ob_start();
$start = microtime(true);
for ($i = 0; $i < MAX_PER_ITERATION; $i++) {
echo "string $variable";
ob_clean();
}
$diff = (microtime(true) - $start);
ob_end_clean();
$times['doublequote'][] = $diff;
sleep(SLEEP_TIME);
/* Start HEREDOC tests */
echo "\tHeredoc\n";
ob_start();
$start = microtime(true);
for ($i = 0; $i < MAX_PER_ITERATION; $i++) {
echo <<< EOT
string {$variable}
EOT;
ob_clean();
}
$diff = (microtime(true) - $start);
ob_end_clean();
$times['heredoc'][] = $diff;
sleep(SLEEP_TIME);
}
foreach ($times as $type => $results) {
echo $type."\n";
foreach ($results as $r) {
echo "\t\t".$r."\n";
}
$avg = array_sum($results) / sizeof($results);
echo "\tAvg: ".$avg."\n";
}
Summary Results
Unsurprisingly, the Single Quoted strings are the fastest: as they don't require parsing for variables or special characters (e.g. \n
), they run quicker than the others both for simple strings and for variables.
- Simple String:
0.3838947773
seconds for 1 Million executions - String+Variable:
0.532834816
seconds for 1 Million executions
Heredoc performs a bit slower than Single Quoted strings, but faster than Double Quoted ones, especially when without variables.
- Simple String:
0.387871933
seconds for 1 Million executions - String+Variable:
0.553892827
seconds for 1 Million executions
Finally Double Quoted strings:
- Simple String:
0.3914105415
seconds for 1 Million executions - String+Variable:
0.5623492718
seconds for 1 Million executions
Complete Results
Below you can see a sneak peak of the final results. If you click on the image or here , you can access a shared spreadsheet with the complete data.
System/Versions
- PHP 7.4.19
- Amazon Linux 2 AMI
- Kernel 4.14.232-177.418.amzn2.x86_64
- 16GB Memory
- 4 Virtual CPUs