PHP中变量扩展与sprintf的性能

eli*_*lon 22 php string performance printf variable-expansion

关于性能,做什么之间有什么区别:

$message = "The request $request has $n errors";
Run Code Online (Sandbox Code Playgroud)

$message = sprintf('The request %s has %d errors', $request, $n);
Run Code Online (Sandbox Code Playgroud)

用PHP?

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

谢谢!

Pek*_*ica 34

不要紧.

任何性能提升都是如此微不足道,以至于你会看到它(仅仅是几秒钟内的改进)只有10000s或100000次迭代 - 即便如此.

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

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

  • 如果你必须显示很多变量,`sprintf`实际上是有用的,其中双引号字符串可能变成象形文字(特别是关联数组).但我倾向于首先使用""因为键入更快:) (4认同)
  • 您对“现实世界情况”的看法相当有限。如果您只编写动态网站,那么通过这些比较,您可能确实在现实世界中没有任何收获。但是 Stackoverflow 上要求性能差异的人通常不会做一个基本的网站项目,所以他的“现实世界”可能与你的非常不同。PHP 可用于处理数百 GB 的数据,因此一毫秒的性能差异可能会导致数小时(或更长时间)的实际性能差异。我的 PHP 脚本需要处理数周。 (4认同)
  • 对于我的钱,在PHP的更高版本中,没有什么比HEREDOC字符串更好. (2认同)

Max*_*sky 26

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

$message = sprintf('The request %s has %d errors', $request, $n);
Run Code Online (Sandbox Code Playgroud)

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

The request $request has no error errors
Run Code Online (Sandbox Code Playgroud)

而第二个将输出:

The request $request has 0 errors
Run Code Online (Sandbox Code Playgroud)

  • 不要相信双引号字符串总是比单引号慢:http://www.codeforest.net/php-myth-busters-using-single-quotes-on-string-is-faster-then-双引号 (2认同)
  • 单引号字符串并不比双引号字符串快。没有运行时差异。 (2认同)
  • @TextGeek解析不会在运行时发生,它会在编译文件时发生.在编译时存在微小的,可忽略的差异,但即使是大的也不重要,因为编译的操作码是缓存的. (2认同)

Pet*_*uss 21

有关"变量扩展与sprintf的"性能分析作出这里.

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

总结基准:PHP针对Double-quoted和Heredoc分辨率进行了优化.关于平均时间的百分比,仅使用计算非常长的字符串,

  • 双引号分辨率:75%
  • heredoc分辨率:82%
  • 单引号连接:93%
  • sprintf格式: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}!".


Eug*_*rov 10

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

\n\n
$message = "The request {$request} has {$n} errors";\n
Run Code Online (Sandbox Code Playgroud)\n\n

你可以简单地自己证明一下:

\n\n

\n\n

$request = "XYZ";\n$n = "0";\n$mtime = microtime(true);\nfor ($i = 0; $i < 1000000; $i++) {\n        $message = "The request {$request} has {$n} errors";\n}\n$ctime = microtime(true);\necho \'\n\n"variable $replacement timing": \'.  ($ctime-$mtime);\n\n\n\n\n$request = "XYZ";\n$n = "0";\n$mtime = microtime(true);\nfor ($i = 0; $i < 1000000; $i++) {\n        $message = \'The request \'.$request.\' has \'.$n.\' errors\';\n}\n$ctime = microtime(true);\necho \'\n\n"concatenation" . $timing: \'.  ($ctime-$mtime);\n\n\n\n$request = "XYZ";\n$n = "0";\n$mtime = microtime(true);\nfor ($i = 0; $i < 1000000; $i++) {\n        $message = sprintf(\'The request %s has %d errors\', $request, $n);\n}\n$ctime = microtime(true);\necho \'\n\nsprintf("%s", $timing): \'.  ($ctime-$mtime);\n
Run Code Online (Sandbox Code Playgroud)\n\n

PHP 7.3.5的结果:

\n\n
\n

“变量$替换时间”:0.091434955596924

\n\n

“串联”。$计时:0.11175799369812

\n\n

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

\n
\n\n

也许您已经发现了诸如“使用 sprintf 而不是双引号中包含的变量,它\xe2\x80\x99s 速度大约 10 倍”之类的建议。\'有哪些好的 PHP 性能技巧?

\n\n

我发现这是事实,但有一天。即PHP 5.2.*之前

\n\n

以下是PHP 5.1.6时期的示例:

\n\n
\n

“变量$替换时间”:0.67681694030762

\n\n

“串联”。$计时:0.24738907814026

\n\n

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

\n
\n