PHP中变量扩展与sprintf的性能

时间:2011-08-22 12:14:52

标签: php string performance printf variable-expansion

关于表现,做:

之间有什么区别吗?
$message = "The request $request has $n errors";

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

我会说调用函数涉及更多东西,但我不知道PHP在幕后做什么来扩展变量名。

谢谢!

6 个答案:

答案 0 :(得分:30)

没关系。

任何性能提升都是如此微不足道,以至于你会看到它(作为几秒钟内的改进)只有10000s或100000次迭代 - 如果是这样的话。

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

使用任何使您和其他人的代码最易读和可维护的内容。就我个人而言,sprintf()方法是一个很好的想法 - 我必须考虑自己开始使用它。

答案 1 :(得分:25)

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

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

尽管如此,我认为秒数较慢(因为@Pekka指出差异实际上并不重要),因为函数调用的开销,解析字符串,转换值等等。但请注意,2行代码不等价,因为在第二种情况下,$ n被转换为整数。如果$ n是“无错误”,那么第一行将输出:

The request $request has no error errors

第二个将输出:

The request $request has 0 errors

答案 2 :(得分:20)

对“变量扩展与sprintf”进行了性能分析here

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

总结基准:PHP针对Double-quoted和Heredoc分辨率进行了优化。仅使用

计算非常长的字符串的平均时间百分比
  • 双引号分辨率:75%
  • heredoc分辨率:82%
  • 单引号连接:93%
  • sprintf formating:117%
  • 使用索引参数形成sprintf:133%

请注意,只有sprintf执行一些格式化任务(参见基准测试'%s%s%d%s%f%s'),并且正如@Darhazer所示,它在输出方面有所不同。一个更好的测试是两个基准测试,一个只比较连接时间('%s'格式化程序),其他包括格式化过程 - 例如'%3d%2.2f'和功能等价物,然后将变量扩展为双引号...还有一个使用短模板字符串的基准组合。

PROS和CONS

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

doubled-quoted (和heredoc)的主要优点是一些性能;当与sprintf的位置标记进行比较时,名义占位符的一些可读性和可维护性随着参数的数量(1之后)而增长。

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

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

答案 3 :(得分:2)

对于将多个String变量注入String,第一个变速器会更快。

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

?>

答案 4 :(得分:1)

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

$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

     

“串联”。 $ timing:0.11175799369812

     

sprintf(“%s”,$ timing):0.17482495307922

可能您已经发现了一些建议,例如“使用sprintf代替双引号中包含的变量,它快10倍左右”。 What are some good PHP performance tips?

我看到这是事实,但是有一天。即在 PHP 5.2。*

之前

这里是 PHP 5.1.6 时代的一个示例:

  

“可变的$替换时间”:0.67681694030762

     

“串联”。 $ timing:0.24738907814026

     

sprintf(“%s”,$ timing):0.61580610275269

答案 5 :(得分:0)

最初考虑单个变量赋值的上下文时,第一个是最快的,可以通过查看各种基准来看到。也许,使用核心PHP函数的sprintf风格可以允许更多可扩展的代码,并且可以更好地优化opcache或apc等字节码级缓存机制。换句话说,当使用sprintf方法时,特定大小的应用程序可以使用更少的代码。缓存到RAM中的代码越少,对其他东西或更多脚本的RAM就越多。但是,这只有在您的脚本无法通过评估适当放入RAM时才会有用。