PHP 中变量扩展与 sprintf 的性能比较

发布于 2024-11-30 22:21:05 字数 284 浏览 1 评论 0原文

in PHP之间有什么区别吗

$message = "The request $request has $n errors";

关于性能,在 PHP 中 do:和

$message = sprintf('The request %s has %d errors', $request, $n);

我想说调用函数涉及更多的东西,但我不知道 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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

鲜肉鲜肉永远不皱 2024-12-07 22:21:05

不要紧。

任何性能提升都非常微不足道,以至于您只能在 10000 或 100000 次迭代中才能看到它(作为百分之几秒的改进)——即使那样。

有关具体数字,请参阅此基准测试。您可以看到它必须使用 100,000 个函数调用生成 1MB 以上的数据,才能在数百毫秒内实现可测量的差异。几乎不是现实生活中的情况。即使是最慢的方法(“带有位置参数的 sprintf()”)也只需要 0.00456 毫秒,而最快的则需要 0.00282 毫秒。对于任何需要 100,000 个字符串输出调用的操作,您将面临其他因素(例如网络流量),这些因素将比您通过优化此操作可以节省的 100 毫秒慢一个数量级。

使用任何使您的代码对您和其他人来说最具可读性和可维护性的东西。对我个人来说,sprintf() 方法是一个好主意 - 我必须考虑自己开始使用它。

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.

独享拥抱 2024-12-07 22:21:05

在所有情况下,第二个不会更快,因为您提供的是双引号字符串,也必须解析变量。如果您要进行微优化,正确的方法是:

$message = sprintf('The request %s has %d errors', $request, $n);

不过,我相信秒数会更慢(正如@Pekka指出的那样,差异实际上并不重要),因为函数调用、解析字符串、转换值的开销,但请注意,这两行代码并不等效,因为在第二种情况下 $n 被转换为整数。如果 $n 是“无错误”,则第一行将输出:

The request $request has no error errors

而第二行将输出:

The request $request has 0 errors

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
北斗星光 2024-12-07 22:21:05

此处进行了有关“变量扩展与 sprintf”的性能分析< /a>.

正如 @pekka 所说,“使您的代码对您和其他人来说最具可读性和可维护性”。当性能增益“低”(〜少于两倍)时,忽略它。

总结基准:PHP 针对双引号和 Heredoc 解析进行了优化。 计算非常长的字符串

  • 尊重平均时间的百分比,仅使用双引号分辨率
  • :75%定界符分辨率:82%
  • 单引号连接:93%
  • sprintf 格式化:117%
  • 带索引参数的 sprintf 格式化:133%

请注意只有 sprintf 执行一些格式化任务(请参阅基准测试的 '%s%s%d%s%f%s'),并且@Darhazer 表明,它对输出有一些影响。更好的测试是两个基准,一个仅比较串联时间('%s' 格式化程序),另一个包括格式化过程 - 例如 '%3d%2.2f' 以及将变量扩展为双引号之前的功能等效项......还有更多使用短模板字符串的基准组合。

优点和缺点

正如基准测试所示,sprintf 的主要优点是成本非常低的格式化程序 (!)。对于通用模板,我建议使用 vsprintf 函数。

双引号(和heredoc)的主要优点是一些性能;与 sprintf 的位置标记相比,标称占位符的一些可读性和可维护性随着参数数量(1 之后)而增长。

使用索引占位符是 sprintf 可维护性的一半。

注意:仅在确实必要时才使用单引号连接。请记住,PHP 支持安全语法,例如 "Hello {$user}_my_brother!" 和引用,例如 "Hello {$this->name}!"

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

温折酒 2024-12-07 22:21:05

我很惊讶,但是对于 PHP 7.*“$variables replacement”是最快的方法

$message = "The request {$request} has {$n} errors";

您可以简单地自己证明这一点:

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

PHP 7.3.5 的结果:

“变量$替换时间”:0.091434955596924

“串联”。 $计时:0.11175799369812

sprintf("%s", $timing): 0.17482495307922

也许您已经找到了诸如“使用 sprintf 而不是双引号中包含的变量,大约快 10 倍”之类的建议。 有哪些好的 PHP 性能技巧?

我明白了这是事实,但有一天。即在 PHP 5.2.* 之前

,下面是 PHP 5.1.6 的情况示例:

“变量$替换时机”:0.67681694030762

“串联”。 $计时:0.24738907814026

sprintf("%s", $timing): 0.61580610275269

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

私野 2024-12-07 22:21:05

对于将多个字符串变量注入到字符串中,第一个变量会更快。

$message = "The request $request has $n errors";

对于单次注入,点(.)连接会更快。

$message = 'The request '.$request.' has 0 errors';

进行十亿次循环的迭代并找出差异。

例如:

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

?>

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

?>
情域 2024-12-07 22:21:05

最终,当考虑单个变量赋值的上下文时,第一个是最快的,这可以通过查看各种基准来看出。不过,也许使用核心 PHP 函数的 sprintf 风格可以允许更多可扩展的代码,并更好地针对字节码级缓存机制(如 opcache 或 apc)进行优化。换句话说,特定大小的应用程序在使用 sprintf 方法时可以使用更少的代码。需要缓存到 RAM 中的代码越少,用于其他操作或脚本的 RAM 就越多。然而,只有当您的脚本无法使用评估正确放入 RAM 时,这才有意义。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文