Performance of variable expansion vs. sprintf in PHP - php

Regarding performance, is there any difference between doing:
$message = "The request $request has $n errors";
and
$message = sprintf('The request %s has %d errors', $request, $n);
in PHP?
I would say that calling a function involves more stuff, but I do not know what's PHP doing behind the scenes to expand variables names.
Thanks!

It does not matter.
Any performance gain would be so minuscule that you would see it (as an improvement in the hundreths of seconds) only with 10000s or 100000s of iterations - if even then.
For specific numbers, see this benchmark. You can see it has to generate 1MB+ of data using 100,000 function calls to achieve a measurable difference in the hundreds of milliseconds. Hardly a real-life situation. Even the slowest method ("sprintf() with positional params") takes only 0.00456 milliseconds vs. 0.00282 milliseconds with the fastest. For any operation requiring 100,000 string output calls, you will have other factors (network traffic, for example) that will be an order of magniture slower than the 100ms you may be able to save by optimizing this.
Use whatever makes your code most readable and maintainable for you and others. To me personally, the sprintf() method is a neat idea - I have to think about starting to use that myself.

In all cases the second won't be faster, since you are supplying a double-quoted string, which have to be parsed for variables as well. If you are going for micro-optimization, the proper way is:
$message = sprintf('The request %s has %d errors', $request, $n);
Still, I believe the seconds is slower (as #Pekka pointed the difference actually do not matter), because of the overhead of a function call, parsing string, converting values, etc. But please, note, the 2 lines of code are not equivalent, since in the second case $n is converted to integer. if $n is "no error" then the first line will output:
The request $request has no error errors
While the second one will output:
The request $request has 0 errors

A performance analysis about "variable expansion vs. sprintf" was made here.
As #pekka says, "makes your code most readable and maintainable for you and others". When the performance gains are "low" (~ less than twice), ignore it.
Summarizing the benchmark: PHP is optimized for Double-quoted and Heredoc resolutions. Percentuals to respect of average time, to calculating a very long string using only,
double-quoted resolution: 75%
heredoc resolution: 82%
single-quote concatenation: 93%
sprintf formating: 117%
sprintf formating with indexed params: 133%
Note that only sprintf do some formating task (see benchmark's '%s%s%d%s%f%s'), and as #Darhazer shows, it do some difference on output. A better test is two benchmarks, one only comparing concatenation times ('%s' formatter), other including formatting process — for example '%3d%2.2f' and functional equivalents before expand variables into double-quotes... And more one benchmark combination using short template strings.
PROS and CONS
The main advantage of sprintf is, as showed by benchmarks, the very low-cost formatter (!). For generic templating I suggest the use of the vsprintf function.
The main advantages of doubled-quoted (and heredoc) are some performance; and some readability and maintainability of nominal placeholders, that grows with the number of parameters (after 1), when comparing with positional marks of sprintf.
The use of indexed placeholders are at the halfway of maintainability with sprintf.
NOTE: not use single-quote concatenation, only if really necessary. Remember that PHP enable secure syntax, like "Hello {$user}_my_brother!", and references like "Hello {$this->name}!".

I am surprised, but for PHP 7.* "$variables replacement" is the fastest approach:
$message = "The request {$request} has {$n} errors";
You can simply prove it yourself:
$request = "XYZ";
$n = "0";
$mtime = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$message = "The request {$request} has {$n} errors";
}
$ctime = microtime(true);
echo '
"variable $replacement timing": '. ($ctime-$mtime);
$request = "XYZ";
$n = "0";
$mtime = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$message = 'The request '.$request.' has '.$n.' errors';
}
$ctime = microtime(true);
echo '
"concatenation" . $timing: '. ($ctime-$mtime);
$request = "XYZ";
$n = "0";
$mtime = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$message = sprintf('The request %s has %d errors', $request, $n);
}
$ctime = microtime(true);
echo '
sprintf("%s", $timing): '. ($ctime-$mtime);
The result for PHP 7.3.5:
"variable $replacement timing": 0.091434955596924
"concatenation" . $timing: 0.11175799369812
sprintf("%s", $timing): 0.17482495307922
Probably you already found recommendations like 'use sprintf instead of variables contained in double quotes, it’s about 10x faster.' What are some good PHP performance tips?
I see it was the truth but one day. Namely before the PHP 5.2.*
Here is a sample of how it was those days PHP 5.1.6:
"variable $replacement timing": 0.67681694030762
"concatenation" . $timing: 0.24738907814026
sprintf("%s", $timing): 0.61580610275269

For Injecting Multiple String variables into a String, the First one will be faster.
$message = "The request $request has $n errors";
And For a single injection, dot(.) concatenation will be faster.
$message = 'The request '.$request.' has 0 errors';
Do the iteration with a billion loop and find the difference.
For eg :
<?php
$request = "XYZ";
$n = "0";
$mtime = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$message = "The request {$request} has {$n} errors";
}
$ctime = microtime(true);
echo ($ctime-$mtime);
?>

Ultimately the 1st is the fastest when considering the context of a single variable assignment which can be seen by looking at various benchmarks. Perhaps though, using the sprintf flavor of core PHP functions could allow for more extensible code and be better optimized for bytecode level caching mechanisms like opcache or apc. In other words, a particular sized application could use less code when utilizing the sprintf method. The less code you have to cache into RAM, the more RAM you have for other things or more scripts. However, this only matters if your scripts wouldn't properly fit into RAM using evaluation.

Related

Is there any difference in performance between assigning a long string to a variable and subsequently appending smaller strings to a variable?

As the title says, is there a difference in performance between:
$var = "Very long string to add";
and
$var = "Appending";
$var.= "subsequentially";
$var.= "short";
$var.= "strings";
I like to use the second method becouse i can keep the code more clean, but I'm worried multiple assignments could affect performance, is it something worth worrying about?
Is there a way to test it maybe?
Yes, there is a way to measure it ... see this function ... but hard to say how much precise this would be.
Test example is below.
<?php
$s1 = microtime(true);
$var1 = "Very long string to add";
$e1 = microtime(true);
$s2 = microtime(true);
$var2 = "Appending";
$var2.= "subsequentially";
$var2.= "short";
$var2.= "strings";
$e2 = microtime(true);
echo 'Big string: ' . number_format($e1 - $s1, 9, '.', '') . 's';
echo PHP_EOL;
echo 'Appended: ' . number_format($e2 - $s2, 9, '.', '') . 's';
Tests looked mostly like this:
Big string: 0.000001907s
Appended: 0.000002146s
Big string: 0.000000954s
Appended: 0.000003099s
Big string: 0.000000954s
Appended: 0.000002146s
Both solutions take up max 1 or 2 micro-seconds, so, ... yes, the appending technique is a little more performance-costly, but not so significantly that you should care :) ...
... unless you count every micro-second, then i would recommend you a language other than PHP.

PHP's array_slice vs Python's splitting arrays

Some background
I was having a go at the common "MaxProfit" programming challenge. It basically goes like this:
Given a zero-indexed array A consisting of N integers containing daily
prices of a stock share for a period of N consecutive days, returns
the maximum possible profit from one transaction during this period.
I was quite pleased with this PHP algorithm I came up, having avoided the naive brute-force attempt:
public function maxProfit($prices)
{
$maxProfit = 0;
$key = 0;
$n = count($prices);
while ($key < $n - 1) {
$buyPrice = $prices[$key];
$maxFuturePrice = max( array_slice($prices, $key+1) );
$profit = $maxFuturePrice - $buyPrice;
if ($profit > $maxProfit) $maxProfit = $profit;
$key++;
}
return $maxProfit;
}
However, having tested my solution it seems to perform badly performance-wise, perhaps even in O(n2) time.
I did a bit of reading around the subject and discovered a very similar python solution. Python has some quite handy array abilities which allow splitting an array with a a[s : e] syntax, unlike in PHP where I used the array_slice function. I decided this must be the bottleneck so I did some tests:
Tests
PHP array_slice()
$n = 10000;
$a = range(0,$n);
$start = microtime(1);
foreach ($a as $key => $elem) {
$subArray = array_slice($a, $key);
}
$end = microtime(1);
echo sprintf("Time taken: %sms", round(1000 * ($end - $start), 4)) . PHP_EOL;
Results:
$ php phpSlice.php
Time taken: 4473.9199ms
Time taken: 4474.633ms
Time taken: 4499.434ms
Python a[s : e]
import time
n = 10000
a = range(0, n)
start = time.time()
for key, elem in enumerate(a):
subArray = a[key : ]
end = time.time()
print "Time taken: {0}ms".format(round(1000 * (end - start), 4))
Results:
$ python pySlice.py
Time taken: 213.202ms
Time taken: 212.198ms
Time taken: 215.7381ms
Time taken: 213.8121ms
Question
Why is PHP's array_slice() around 20x less efficient than Python?
Is there an equivalently efficient method in PHP that achieves the above and thus hopefully makes my maxProfit algorithm run in O(N) time? Edit I realise my implementation above is not actually O(N), but my question still stands regarding the efficiency of slicing arrays.
I don't really know, but PHP's arrays are messed up hybrid monsters, maybe that's why. Python's lists are really just lists, not at the same time dictionaries, so they might be simpler/faster because of that.
Yes, do an actual O(n) solution. Your solution isn't just slow because PHP's slicing is apparently slow, it's slow because you obviously have an O(n^2) algorithm. Just walk over the array once, keep track of the minimum price found so far, and check it with the current price. Not something like max over half the array in every single loop iteration.

PHP rand vs mt_rand vs openssl_random_pseudo_bytes

I want to generate a random string and was doing some research and found the following link:
http://golearnphp.com/php-rand-vs-mt_rand-and-openssl_random_pseudo_bytes/
function generateRandom($length) {
$validCharacters = 'abcdefghijklmnopqrstuvwxyz0123456789';
$myKeeper = '';
for ($n = 1; $n < $length; $n++) {
$whichCharacter = rand(0, strlen($validCharacters) - 1);
$myKeeper .= $validCharacters{$whichCharacter};
}
return $myKeeper;
}
function generateRandomdMT($length) {
$validCharacters = 'abcdefghijklmnopqrstuvwxyz0123456789';
$myKeeper = '';
for ($n = 1; $n < $length; $n++) {
$whichCharacter = mt_rand(0, strlen($validCharacters) - 1);
$myKeeper .= $validCharacters{$whichCharacter};
}
return $myKeeper;
}
$start = microtime(true);
echo htmlentities(generateRandom(100000));
var_dump(microtime(true) - $start);
$start = microtime(true);
echo htmlentities(generateRandomdMT(100000));
var_dump(microtime(true) - $start);
$start = microtime(true);
echo htmlentities(substr(base64_encode(openssl_random_pseudo_bytes(100000)), 0, 100000));
var_dump(microtime(true) - $start);
In the post the writer is saying that openssl_random_pseudo_bytes is significant faster then the other two. Is this true? Is openssl_random_pseudo_bytes really that much faster? Is that the correct way to test the "fastness" of functions?
openssl_random_pseudo_bytes created to be crypto strong(check the second param). Rand is old rand function with small period of repeating. MT_Rand is better than rand but not supposed to be used by crypto systems.
I bet that the difference between execution time do not impact on your application.
Also. Those functions return different results. First two return string with 36 possible letters. And third one returns string with 64 possible symbols. Result of two first function is shorter than third one.
If you are making optimization to speed up your application first thing that you should to know: how to profile your code.
In the post the writer is saying that openssl_random_pseudo_bytes is significant faster then the other two. Is this true?
In normal situations mt_rand() is significantly faster than openssl_random_pseudo_bytes().
It's only slower in the test code you've posted because you are comparing apples and oranges. For rand() and mt_rand() you are using complex functions which build up a string one byte at a time, whereas for openssl_random_pseudo_bytes() you're using the raw binary stream it produces with base64_encode() which is going to be much faster.
If you could get a raw binary stream out of mt_rand() or rand(), or a sequence of numbers 0 to 63 from openssl_random_pseudo_bytes(), you could do an apples to apples comparison.
In my testing, I found mt_rand() about 4 times as fast as openssl_random_pseudo_bytes(4) when I used unpack('V', openssl_random_pseudo_bytes(4) & "\xff\xff\xff\x7f") in order to get an equivalent output to mt_rand(). However this is still technically an apples to oranges situation because I'm doing additional processing on one in order to match it to the other, just in the opposite direction to you.
The time you asked this question, there was a bug report here > https://bugs.php.net/bug.php?id=70014 (php 5.6.10) It seems to be fixed in new versions of PHP.
My experience using it has always been unnecessary, I prefer Mt_Rand() but if you are generating random values for encryption purposes like I am doing, then do not use it, you should use random_bytes() ref. https://www.php.net/manual/en/function.random-bytes.php

Which is faster in PHP - sprintf or double quoted strings? [duplicate]

I read somewehere (I thought on codinghorror) that it is bad practice to add strings together as if they are numbers, since like numbers, strings cannot be changed. Thus, adding them together creates a new string. So, I was wondering, what is the best way to add two strings together, when focusing on performance?
Which of these four is better, or is there another way which is better?
//Note that normally at least one of these two strings is variable
$str1 = 'Hello ';
$str2 = 'World!';
$output1 = $str1.$str2; //This is said to be bad
$str1 = 'Hello ';
$output2 = $str1.'World!'; //Also bad
$str1 = 'Hello';
$str2 = 'World!';
$output3 = sprintf('%s %s', $str1, $str2); //Good?
//This last one is probaply more common as:
//$output = sprintf('%s %s', 'Hello', 'World!');
$str1 = 'Hello ';
$str2 = '{a}World!';
$output4 = str_replace('{a}', $str1, $str2);
Does it even matter?
String Concatenation with a dot is definitely the fastest one of the three methods. You will always create a new string, whether you like it or not.
Most likely the fastest way would be:
$str1 = "Hello";
$str1 .= " World";
Do not put them into double-quotes like $result = "$str1$str2"; as this will generate additional overhead for parsing symbols inside the string.
If you are going to use this just for output with echo, then use the feature of echo that you can pass it multiple parameters, as this will not generate a new string:
$str1 = "Hello";
$str2 = " World";
echo $str1, $str2;
For more information on how PHP treats interpolated strings and string concatenation check out Sarah Goleman's blog.
You are always going to create a new string whe concatenating two or more strings together. This is not necessarily 'bad', but it can have performance implications in certain scenarios (like thousands/millions of concatenations in a tight loop). I am not a PHP guy, so I can't give you any advice on the semantics of the different ways of concatenating strings, but for a single string concatenation (or just a few), just make it readable. You are not going to see a performance hit from a low number of them.
Here's the quick and dirty test code, to understand the performance bottlenecks.
Single concat:
$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = sprintf('DELETE FROM `%s` WHERE `ID` = ?', $table);
}
echo 'single sprintf,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = 'DELETE FROM `' . $table . '` WHERE `ID` = ?';
}
echo 'single concat,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = "DELETE FROM `$table` WHERE `ID` = ?";
}
echo 'single "$str",',(microtime(true) - $time)."\n";
I get these results:
single sprintf,0.66322994232178
single concat,0.18625092506409 <-- winner
single "$str",0.19963216781616
Many concats (10):
$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = sprintf('DELETE FROM `%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s` WHERE `ID` = ?', $table, $table, $table, $table, $table, $table, $table, $table, $table, $table);
}
echo 'many sprintf,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = 'DELETE FROM `' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '` WHERE `ID` = ?';
}
echo 'many concat,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = "DELETE FROM `$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table` WHERE `ID` = ?";
}
echo 'many "$str",',(microtime(true) - $time)."\n";
Results:
many sprintf,2.0778489112854
many concats,1.535336971283
many "$str",1.0247709751129 <-- winner
As conclusion, it becomes obvious that single concat via dot (.) char is the fastest. And for cases, when you've got many concats, the best performing method is using direct string injection via "injection: $inject" syntax.
Unless its really large amount of text it really doesnt matter.
As the others said, $str1 . $str2 is perfectly OK in most cases, except in (big) loops.
Note that you overlook some solutions:
$output = "$str1$str2";
and for large number of strings, you can put them in an array, and use implode() to get a string out of them.
Oh, and "adding strings" sounds bad, or at least ambiguous. In most languages, we prefer to speak of string concatenation.
It doesn't matter unless used in a looong loop. In usual cases focus on code readability, even if you lost several processor cycles.
Example 1 and 2 are similar, I don't think there should be much difference, this would be the fastes of all. No. 1 might be slightly faster.
Example 3 will be slower, as sprintf format ('%s %s') needs to be parsed.
Example 4 does the replace, which involves searching within a string - additional thing to do, takes more time.
But firstly, is concatenating strings a performance problem? It's very unlikely, you should profile code to measure how much time does it take to run it. Then, replace the concatenating method with a different one and time again.
If you identify it as a problem, try googling for php string builder class (there are some to be found) or write your own.
Found this post from Google, and thought I'd run some benchmarks, as I was curious what the result would be. (Benchmarked over 10,000 iterations using a benchmarker that subtracts its own overhead.)
Which 2 strings 10 strings 50 strings
----------------------------------------------------------------
$a[] then implode() 2728.20 ps 6.02 μs 22.73 μs
$a . $a . $a 496.44 ps 1.48 μs 7.00 μs
$b .= $a 421.40 ps ★ 1.26 μs 5.56 μs
ob_start() and echo $a 2278.16 ps 3.08 μs 8.07 μs
"$a$a$a" 482.87 ps 1.21 μs ★ 4.94 μs ★
sprintf() 1543.26 ps 3.21 μs 12.08 μs
So there's not much in it. Probably good to avoid sprintf() and implode() if you need something to be screaming fast, but there's not much difference between all the usual methods.
there are 3 types of string joining operations.
Concatenate, take 2 string, allocate memory size length1+length2 and copy each into the new memory. quickest for 2 strings. However, concatenating 10 strings then requires 9 concat operations. The memory used is the 1st string 10 times, 2nd string 10 times, 3rd string 9 times, 4th string 8 times, etc. Runs X+1 +(X-1)*2 operations using more memory each cycle.
sprintf (array_merge, join, etc), take all the strings together, sum their length, allocate a new string of size sum, then copy each string into its respective place. memory used is 2*length of all initial strings, and operations is 2*X (each length, each copy)
ob (output buffer) allocate a generic 4k chunk and copies each string to it. memory 4k + each initial string, operations = 2 + X. (start, end, each copy)
Pick your poison.
OB is like using a memory atom bomb to join 2 small strings, but is very effective when there are many joins, loops, conditions or the additions are too dynamic for a clean sprintf.
concat is the most efficient to join a few fixed strings,
sprintf which works better for building a string out of fixed values at one time.
I don't know which routine php uses in this situation: "$x $y $z", might just be reduced to an inline $x . " " . $y . " " . $z
The advice you have read may have been related to the echo function, for which it's quicker to use commas, eg:
echo $str1, $str2;
Another approach is to build up a string in a variable (eg using the . operator) then echo the whole string at the end.
You could test this yourself using the microtime function (you'll need to make a loop that repeats eg 1,000 or 100,000 times to make the numbers significant). But of the four you posted, the first one is likely to be the fastest. It's also the most readable - the others don't really make sense programmatically.
This is not a solution for 2 strings, but when you thinking of joining more strings best way like that:
$tmp=srray();
for(;;) $tmp[]='some string';
$str=implode('',$tmp);
It's faster to create array element and join them all at once, than join them hundred times.
I'm not a PHP guru, however, in many other languages (e.g. Python), the fastest way to build a long string out of many smaller strings is to append the strings you want to concatenate to a list, and then to join them using a built-in join method. For example:
$result = array();
array_push("Hello,");
array_push("my");
array_push("name");
array_push("is");
array_push("John");
array_push("Doe.");
$my_string = join(" ", $result);
If you are building a huge string in a tight loop, the fastest way to do it is by appending to the array and then joining the array at the end.
Note: This entire discussion hinges on the performance of an array_push. You need to be appending your strings to a list in order for this to be effective on very large strings. Because of my limited exposure to php, I'm not sure if such a structure is available or whether php's array is fast at appending new elements.
For nearly 2 years after last post in this thread, I think that below solution may be the fastest for huge number of tight loops:
ob_start();
echo $str1;
echo $str2;
.
.
.
echo $str_n;
$finalstr = ob_get_clean();
This method ensures a flat storage of all strings and no processing or concatenation overhead. With the final code line, you get entire buffer as well. You can safely run loops instead of independent echos.

What is the best way to add two strings together?

I read somewehere (I thought on codinghorror) that it is bad practice to add strings together as if they are numbers, since like numbers, strings cannot be changed. Thus, adding them together creates a new string. So, I was wondering, what is the best way to add two strings together, when focusing on performance?
Which of these four is better, or is there another way which is better?
//Note that normally at least one of these two strings is variable
$str1 = 'Hello ';
$str2 = 'World!';
$output1 = $str1.$str2; //This is said to be bad
$str1 = 'Hello ';
$output2 = $str1.'World!'; //Also bad
$str1 = 'Hello';
$str2 = 'World!';
$output3 = sprintf('%s %s', $str1, $str2); //Good?
//This last one is probaply more common as:
//$output = sprintf('%s %s', 'Hello', 'World!');
$str1 = 'Hello ';
$str2 = '{a}World!';
$output4 = str_replace('{a}', $str1, $str2);
Does it even matter?
String Concatenation with a dot is definitely the fastest one of the three methods. You will always create a new string, whether you like it or not.
Most likely the fastest way would be:
$str1 = "Hello";
$str1 .= " World";
Do not put them into double-quotes like $result = "$str1$str2"; as this will generate additional overhead for parsing symbols inside the string.
If you are going to use this just for output with echo, then use the feature of echo that you can pass it multiple parameters, as this will not generate a new string:
$str1 = "Hello";
$str2 = " World";
echo $str1, $str2;
For more information on how PHP treats interpolated strings and string concatenation check out Sarah Goleman's blog.
You are always going to create a new string whe concatenating two or more strings together. This is not necessarily 'bad', but it can have performance implications in certain scenarios (like thousands/millions of concatenations in a tight loop). I am not a PHP guy, so I can't give you any advice on the semantics of the different ways of concatenating strings, but for a single string concatenation (or just a few), just make it readable. You are not going to see a performance hit from a low number of them.
Here's the quick and dirty test code, to understand the performance bottlenecks.
Single concat:
$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = sprintf('DELETE FROM `%s` WHERE `ID` = ?', $table);
}
echo 'single sprintf,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = 'DELETE FROM `' . $table . '` WHERE `ID` = ?';
}
echo 'single concat,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = "DELETE FROM `$table` WHERE `ID` = ?";
}
echo 'single "$str",',(microtime(true) - $time)."\n";
I get these results:
single sprintf,0.66322994232178
single concat,0.18625092506409 <-- winner
single "$str",0.19963216781616
Many concats (10):
$iterations = 1000000;
$table = 'FOO';
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = sprintf('DELETE FROM `%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s`,`%s` WHERE `ID` = ?', $table, $table, $table, $table, $table, $table, $table, $table, $table, $table);
}
echo 'many sprintf,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = 'DELETE FROM `' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '`,`' . $table . '` WHERE `ID` = ?';
}
echo 'many concat,',(microtime(true) - $time)."\n";
$time = microtime(true);
for ($i = 0; $i < $iterations; $i++) {
$sql = "DELETE FROM `$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table`,`$table` WHERE `ID` = ?";
}
echo 'many "$str",',(microtime(true) - $time)."\n";
Results:
many sprintf,2.0778489112854
many concats,1.535336971283
many "$str",1.0247709751129 <-- winner
As conclusion, it becomes obvious that single concat via dot (.) char is the fastest. And for cases, when you've got many concats, the best performing method is using direct string injection via "injection: $inject" syntax.
Unless its really large amount of text it really doesnt matter.
As the others said, $str1 . $str2 is perfectly OK in most cases, except in (big) loops.
Note that you overlook some solutions:
$output = "$str1$str2";
and for large number of strings, you can put them in an array, and use implode() to get a string out of them.
Oh, and "adding strings" sounds bad, or at least ambiguous. In most languages, we prefer to speak of string concatenation.
It doesn't matter unless used in a looong loop. In usual cases focus on code readability, even if you lost several processor cycles.
Example 1 and 2 are similar, I don't think there should be much difference, this would be the fastes of all. No. 1 might be slightly faster.
Example 3 will be slower, as sprintf format ('%s %s') needs to be parsed.
Example 4 does the replace, which involves searching within a string - additional thing to do, takes more time.
But firstly, is concatenating strings a performance problem? It's very unlikely, you should profile code to measure how much time does it take to run it. Then, replace the concatenating method with a different one and time again.
If you identify it as a problem, try googling for php string builder class (there are some to be found) or write your own.
Found this post from Google, and thought I'd run some benchmarks, as I was curious what the result would be. (Benchmarked over 10,000 iterations using a benchmarker that subtracts its own overhead.)
Which 2 strings 10 strings 50 strings
----------------------------------------------------------------
$a[] then implode() 2728.20 ps 6.02 μs 22.73 μs
$a . $a . $a 496.44 ps 1.48 μs 7.00 μs
$b .= $a 421.40 ps ★ 1.26 μs 5.56 μs
ob_start() and echo $a 2278.16 ps 3.08 μs 8.07 μs
"$a$a$a" 482.87 ps 1.21 μs ★ 4.94 μs ★
sprintf() 1543.26 ps 3.21 μs 12.08 μs
So there's not much in it. Probably good to avoid sprintf() and implode() if you need something to be screaming fast, but there's not much difference between all the usual methods.
there are 3 types of string joining operations.
Concatenate, take 2 string, allocate memory size length1+length2 and copy each into the new memory. quickest for 2 strings. However, concatenating 10 strings then requires 9 concat operations. The memory used is the 1st string 10 times, 2nd string 10 times, 3rd string 9 times, 4th string 8 times, etc. Runs X+1 +(X-1)*2 operations using more memory each cycle.
sprintf (array_merge, join, etc), take all the strings together, sum their length, allocate a new string of size sum, then copy each string into its respective place. memory used is 2*length of all initial strings, and operations is 2*X (each length, each copy)
ob (output buffer) allocate a generic 4k chunk and copies each string to it. memory 4k + each initial string, operations = 2 + X. (start, end, each copy)
Pick your poison.
OB is like using a memory atom bomb to join 2 small strings, but is very effective when there are many joins, loops, conditions or the additions are too dynamic for a clean sprintf.
concat is the most efficient to join a few fixed strings,
sprintf which works better for building a string out of fixed values at one time.
I don't know which routine php uses in this situation: "$x $y $z", might just be reduced to an inline $x . " " . $y . " " . $z
The advice you have read may have been related to the echo function, for which it's quicker to use commas, eg:
echo $str1, $str2;
Another approach is to build up a string in a variable (eg using the . operator) then echo the whole string at the end.
You could test this yourself using the microtime function (you'll need to make a loop that repeats eg 1,000 or 100,000 times to make the numbers significant). But of the four you posted, the first one is likely to be the fastest. It's also the most readable - the others don't really make sense programmatically.
This is not a solution for 2 strings, but when you thinking of joining more strings best way like that:
$tmp=srray();
for(;;) $tmp[]='some string';
$str=implode('',$tmp);
It's faster to create array element and join them all at once, than join them hundred times.
I'm not a PHP guru, however, in many other languages (e.g. Python), the fastest way to build a long string out of many smaller strings is to append the strings you want to concatenate to a list, and then to join them using a built-in join method. For example:
$result = array();
array_push("Hello,");
array_push("my");
array_push("name");
array_push("is");
array_push("John");
array_push("Doe.");
$my_string = join(" ", $result);
If you are building a huge string in a tight loop, the fastest way to do it is by appending to the array and then joining the array at the end.
Note: This entire discussion hinges on the performance of an array_push. You need to be appending your strings to a list in order for this to be effective on very large strings. Because of my limited exposure to php, I'm not sure if such a structure is available or whether php's array is fast at appending new elements.
For nearly 2 years after last post in this thread, I think that below solution may be the fastest for huge number of tight loops:
ob_start();
echo $str1;
echo $str2;
.
.
.
echo $str_n;
$finalstr = ob_get_clean();
This method ensures a flat storage of all strings and no processing or concatenation overhead. With the final code line, you get entire buffer as well. You can safely run loops instead of independent echos.

Categories