30

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!

elitalon
  • 9,191
  • 10
  • 50
  • 86

6 Answers6

43

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.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 6
    `sprintf` is actually useful if you have to display a lot of variables, where a double-quoted string may turn into something hieroglyphic (specially with associative arrays). But I tend to use "" first because is faster to type :) – elitalon Aug 22 '11 at 13:16
  • 2
    For my money, in the later versions of PHP, nothing beats a HEREDOC string. – user1119648 Mar 25 '14 at 00:24
  • @peter what type of benchmark do you expect when the answer is saying "there is no point in benchmarking this because there is not going to be any real-world performance difference"? :) – Pekka May 05 '17 at 09:22
  • How do you know whether the performance gain would be miniscule? – Peter Chaula May 05 '17 at 09:26
  • 1
    @peter from 15 years of experience, having benchmarked stuff in the past, and, to provide a source, similar benchmarks like [this one.](http://judebert.com/progress/archives/204-PHP-String-Formatting-Performance.html) The benchmark 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 0.00456 milliseconds vs. 0.00282 milliseconds with the fastest. – Pekka May 05 '17 at 09:35
  • @Pekka웃 That comment ought to be part of the answer. +1 – Peter Chaula May 05 '17 at 10:05
  • @peter fair enough. Edited answer. – Pekka May 05 '17 at 10:11
  • 3
    You have a quite limited view on "real world situations". If you only write dynamic websites you might indeed have a real world non-gain by those comparisons. But a person on Stackoverflow asking for performance difference is usually not doing a basic website project, so his "real world" might be very different from yours. PHP can be used to process hundreds of gigabytes of data, so a performance difference of a millisecond can result in hours (or more) of actual performance difference. I have PHP scripts that process for weeks. – John Apr 29 '21 at 16:17
32

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
Ethan
  • 4,295
  • 4
  • 25
  • 44
Maxim Krizhanovsky
  • 26,265
  • 5
  • 59
  • 89
  • Truth is I wrote it with single quotes in source code, but when posting the question here I copy/paste the first statement :p Good advice about converting to integer :) – elitalon Aug 22 '11 at 13:03
  • 3
    Do not trust that double-quoted string literals are always slower than single-quoted ones : http://www.codeforest.net/php-myth-busters-using-single-quotes-on-string-is-faster-then-double-quotes – Vince Apr 29 '15 at 07:59
  • 2
    Single-quoted strings are no faster than double-quoted strings. There is no runtime difference. – Andrea Dec 01 '15 at 11:00
  • @Andrea Reference or reason? It's hard to believe that variable interpolation (esp. the parsing to accomplish it) costs nothing (granted, as many have pointed out, it will not likely be enough to affect performance). – TextGeek Oct 29 '16 at 16:12
  • 3
    @TextGeek Parsing doesn't happen at runtime, it happens when the file is compiled. There is a tiny, negligible difference at compile-time, but even a large one wouldn't matter, because compiled opcodes are cached. – Andrea Oct 29 '16 at 19:14
  • Single quoted strings have almost no performance benefit because parsing still has to happen. PHP must parse for `\'` and "\\" to show `'` and "\" respectively, which isn't free. – Adambean Jul 23 '19 at 07:45
  • This was correct but for the PHP5. Please see my comment below https://stackoverflow.com/questions/7147305/performance-of-variable-expansion-vs-sprintf-in-php/58917133#58917133 – Eugene Kaurov Dec 10 '19 at 17:21
22

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}!".

Community
  • 1
  • 1
Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
  • Everyone at the link you posted has posted comments disagreeing with these results. And, these disagreements are logical. Concat does not use temporary variables, string interpolation does. How could the former be slower? – HoldOffHunger Apr 09 '18 at 17:27
  • Hi @HoldOffHunger, can you fix it? The answer now is a Wiki, you can edit. – Peter Krauss Apr 10 '18 at 00:29
7

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

Eugene Kaurov
  • 2,356
  • 28
  • 39
2

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);

?>
  • 4
    A loop might not show the real difference due to CPU branch prediction: The CPU might already know what's going to happen because you do the same thing over and over. – Emil Vikström Oct 20 '14 at 21:24
0

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.

Shapeshifter
  • 510
  • 6
  • 11