56

(假设 php5)考虑

<?php

    $foo = 'some words';

    //case 1
    print "these are $foo";

    //case 2
    print "these are {$foo}";

    //case 3
    print 'these are ' . $foo;
?>

1和2差别大吗?

如果不是,那么在 1/2 和 3 之间呢?

4

15 回答 15

108

至少从 2012 年 1 月开始,性能差异就变得无关紧要了,而且可能更早:

Single quotes: 0.061846971511841 seconds
Double quotes: 0.061599016189575 seconds

PHP 的早期版本可能有所不同——我个人更喜欢单引号而不是双引号,所以这是一个方便的区别。文章的结论提出了一个很好的观点:

永远不要相信不是你自己伪造的统计数据。

(虽然文章引用了这句话,但最初的俏皮话很可能被错误地归因于温斯顿丘吉尔,由约瑟夫戈培尔的宣传部发明,将丘吉尔描绘成一个骗子:

Ich traue keiner Statistik, die ich nicht selbst gefälscht habe。

这大致翻译为“我不相信我没有伪造自己的统计数据。”)

于 2009-01-27T02:53:53.920 回答
47

好吧,就像所有“现实生活中什么可能更快”的问题一样,你无法通过现实生活中的测试。

function timeFunc($function, $runs)
{
  $times = array();

  for ($i = 0; $i < $runs; $i++)
  {
    $time = microtime();
    call_user_func($function);
    $times[$i] = microtime() - $time;
  }

  return array_sum($times) / $runs;
}

function Method1()
{ 
  $foo = 'some words';
  for ($i = 0; $i < 10000; $i++)
    $t = "these are $foo";
}

function Method2()
{
  $foo = 'some words';
  for ($i = 0; $i < 10000; $i++)
    $t = "these are {$foo}";
}

function Method3()
 {
  $foo = 'some words';
  for ($i = 0; $i < 10000; $i++)
    $t = "these are " . $foo;
}

print timeFunc('Method1', 10) . "\n";
print timeFunc('Method2', 10) . "\n";
print timeFunc('Method3', 10) . "\n";

运行几次以将所有内容分页,然后...

0.0035568

0.0035388

0.0025394

因此,正如预期的那样,插值实际上是相同的(噪声水平差异,可能是由于插值引擎需要处理的额外字符)。直接串联大约是速度的 66%,这并没有太大的冲击。插值解析器会查找,发现无事可做,然后以简单的内部字符串 concat 结束。即使 concat 很昂贵,插值器仍然必须这样做,毕竟解析变量和修剪/复制原始字符串的工作。

索姆纳特的更新:

我将 Method4() 添加到上述实时逻辑中。

function Method4()
 {
  $foo = 'some words';
  for ($i = 0; $i < 10000; $i++)
    $t = 'these are ' . $foo;
}

print timeFunc('Method4', 10) . "\n";

Results were:

0.0014739
0.0015574
0.0011955
0.001169

当您只声明一个字符串而无需解析该字符串时,为什么要混淆 PHP 调试器来解析。我希望你明白我的意思。

于 2008-08-17T15:10:24.843 回答
24

实时基准:

http://phpbench.com/

使用单引号和双引号连接变量时,实际上存在细微差别。

于 2009-01-27T04:08:03.113 回答
18

使用@Adam 的测试

"these are " . $foo

请注意,以下内容甚至更快:

'these are ' . $foo;

这是由于这样一个事实,即双引号“字符串”被评估,其中单引号“字符串”按原样...

于 2008-08-17T15:44:57.443 回答
12

不要太着迷于尝试优化 PHP 中的字符串操作。如果您的数据库查询写得不好或者您没有使用任何类型的缓存方案,则连接与插值是没有意义的(在现实世界的性能中)。以这样一种方式编写字符串操作,以便以后调试代码很容易,性能差异可以忽略不计。

@uberfuzzy 假设这只是一个关于语言细节的问题,我想这很好。我只是想补充一点,与实际性能下降(例如糟糕的数据库查询)相比,比较现实世界应用程序中单引号、双引号和heredoc 之间的性能毫无意义。

于 2008-08-19T13:12:17.407 回答
9

执行时间的任何差异都可以忽略不计。

请参见

不要在这样的微优化上浪费时间。使用分析器来衡量您的应用程序在真实场景中的性能,然后在真正需要的地方进行优化。与在整个代码中应用微优化相比,优化单个草率的 DB 查询可能会带来更大的性能改进。

于 2012-06-19T18:27:54.517 回答
4

连接变量时存在差异......以及您对结果所做的事情......如果您正在做的是将其转储到输出,是否正在输出缓冲。

另外,服务器的内存情况如何?通常,高级平台上的内存管理比低级平台上的更差......

$a = 'parse' . $this; 

正在用户代码平台级别管理内存...

$a = "parse $this";

正在php系统代码平台级别管理内存...

所以这些与 CPU 相关的基准测试并不能说明全部情况。

运行基准测试 1000 次与在尝试同时运行相同模拟 1000 次的服务器上运行基准测试 1000 次...根据应用程序的范围,您可能会得到截然不同的结果。

于 2009-09-16T21:25:50.950 回答
3

我似乎记得论坛软件的开发者 Vanilla 用单引号替换了他代码中的所有双引号,并注意到性能有合理的提升。

不过,我目前似乎无法找到讨论的链接。

于 2009-01-27T03:22:48.493 回答
2

如果您在双引号字符串语法中使用变量,只需添加其他内容:

$foo = "hello {$bar}";

$foo = "hello $bar";

这两个都比

$foo = 'hello' . $bar; 
于 2012-10-12T10:01:43.920 回答
1

双引号可能会慢得多。我从几个地方读到最好这样做

'parse me '.$i.' times'

"parse me $i times"

虽然我会说第二个给你更多可读的代码。

于 2009-01-27T04:36:01.700 回答
0

几乎没有任何区别!查看时间: http: //micro-optimization.com/single-vs-double-quotes

于 2011-05-27T22:10:33.607 回答
0

应该注意的是,当使用 Adam Wright 的示例的修改版本和 3 个变量时,结果是相反的,前两个函数实际上更快、更一致。这是 CLI 上的 PHP 7.1:

function timeFunc($function, $runs)
{
    $times = array();

    for ($i = 0; $i < $runs; $i++)
    {
        $time = microtime();
        call_user_func($function);
        @$times[$i] = microtime() - $time;
    }

    return array_sum($times) / $runs;
}

function Method1()
{ 
    $foo = 'some words';
    $bar = 'other words';
    $bas = 3;
    for ($i = 0; $i < 10000; $i++)
         $t = "these are $foo, $bar and $bas";
}

function Method2()
{
    $foo = 'some words';
    $bar = 'other words';
    $bas = 3;
    for ($i = 0; $i < 10000; $i++)
         $t = "these are {$foo}, {$bar} and {$bas}";
}

function Method3()
{
    $foo = 'some words';
    $bar = 'other words';
    $bas = 3;
    for ($i = 0; $i < 10000; $i++)
         $t = "these are " . $foo . ", " . $bar . " and " .$bas;
}

print timeFunc('Method1', 10) . "\n";
print timeFunc('Method2', 10) . "\n";
print timeFunc('Method3', 10) . "\n";

我也试过用 '3' 而不是整数 3,但我得到了同样的结果。

使用 $bas = 3:

0.0016254
0.0015719
0.0019806

使用 $bas = '3':

0.0016495
0.0015608
0.0022755

应该注意的是,这些结果差异很大(我得到大约 300% 的变化),但平均值似乎相对稳定,几乎(10 个案例中有 9 个)总是显示前两种方法的执行速度更快,方法 2 总是略快于方法1。

总而言之:对于 1 个单一操作(无论是插值还是串联)正确的情况对于组合操作并不总是正确的。

于 2017-04-26T04:56:08.187 回答
0

是的,最初这是关于 PHP5,但几个月后 PHP8 出现了,今天在我的PHP 7.4.5上测试的最佳选择是使用PHP - Nowdoc(在 WIN 10 + Apache 和 CentOs 7 + Apache 上测试):

function Method6(){
    $k1 = 'AAA';
    for($i = 0; $i < 10000; $i ++)$t = <<<'EOF'
K1= 
EOF
.$k1.
<<<'EOF'
K2=
EOF
.$k1;
    }

这里是方法#5(使用Heredoc连接):

function Method5(){
    $k1 = 'AAA';
    for($i = 0; $i < 10000; $i ++)$t = <<<EOF
K1= $k1
EOF
.<<<EOF
K2=$k1 
EOF;
    }

方法1到4在这篇文章的开头

在我所有的测试中,“赢家”是方法#6(Newdoc),不是很容易阅读,但在 CPU 中速度非常快,并且曾经使用过function timeFunc($function)@Adam Wright的函数。

于 2020-07-19T22:08:43.527 回答
0

我已经用以下测试用例测试了 php 7.4 和 php 5.4,这对我来说仍然有点困惑。

<?php
$start_time = microtime(true);
$result = "";
for ($i = 0; $i < 700000; $i++) {
    $result .= "THE STRING APPENDED IS " . $i;
    // AND $result .= 'THE STRING APPENDED IS ' . $i;
    // AND $result .= "THE STRING APPENDED IS $i";
}
echo $result;
$end_time = microtime(true);
echo "<br><br>";
echo ($end_time - $start_time) . " Seconds";

PHP 7.4 输出

 1. "THE STRING APPENDED IS " . $i = 0.16744208335876
 2. 'THE STRING APPENDED IS ' . $i = 0.16724419593811
 3. "THE STRING APPENDED IS $i" = 0.16815495491028

PHP 5.3 输出

 1. "THE STRING APPENDED IS " . $i = 0.27664494514465
 2. 'THE STRING APPENDED IS ' . $i = 0.27818703651428
 3. "THE STRING APPENDED IS $i" = 0.28839707374573

我已经测试了很多次,在 php 7.4 中,似乎所有 3 个测试用例都多次得到相同的结果,但串联在性能上仍然没有一点优势。

于 2021-07-01T08:03:44.710 回答
0

根据@adam-wright 的回答,我想知道速度差异是否在没有连接/字符串中没有变量的情况下发生。

== 我的问题...

  • $array['key']调用还是设置比$array["key"]!?
  • $var = "some text";$var = 'some text';?

==我每次都使用新变量进行测试以避免使用相同的内存地址:

function getArrDblQuote() { 
    $start1 = microtime(true);
    $array1 = array("key" => "value");
    for ($i = 0; $i < 10000000; $i++)
        $t1 = $array1["key"];
    echo microtime(true) - $start1;
}
function getArrSplQuote() {
    $start2 = microtime(true);
    $array2 = array('key' => 'value');
    for ($j = 0; $j < 10000000; $j++)
        $t2 = $array2['key'];
    echo microtime(true) - $start2;
}

function setArrDblQuote() { 
    $start3 = microtime(true);
    for ($k = 0; $k < 10000000; $k++)
        $array3 = array("key" => "value");
    echo microtime(true) - $start3;
}
function setArrSplQuote() {
    $start4 = microtime(true);
    for ($l = 0; $l < 10000000; $l++)
        $array4 = array('key' => 'value');
    echo microtime(true) - $start4;
}

function setStrDblQuote() { 
    $start5 = microtime(true);
    for ($m = 0; $m < 10000000; $m++)
        $var1 = "value";
    echo microtime(true) - $start5;
}
function setStrSplQuote() {
    $start6 = microtime(true);
    for ($n = 0; $n < 10000000; $n++)
        $var2 = 'value';
    echo microtime(true) - $start6;
}

print getArrDblQuote() . "\n<br>";
print getArrSplQuote() . "\n<br>";
print setArrDblQuote() . "\n<br>";
print setArrSplQuote() . "\n<br>";
print setStrDblQuote() . "\n<br>";
print setStrSplQuote() . "\n<br>";

== 我的结果:

数组获取引号2.1978828907013

数组获取引号2.0163490772247

数组集引号1.9173440933228

数组获取引号1.4982950687408

var 设置引号1.485809803009

var 设置引号1.3026781082153

==我的结论!

所以,结果是差异不是很显着。但是,在一个大项目上,我认为它可以有所作为!

于 2021-07-15T09:56:04.250 回答