在php5中使用内联字符串与串联的速度差异?

时间:2008-08-17 13:19:33

标签: php optimization performance

(假设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之间呢?

15 个答案:

答案 0 :(得分:105)

自2012年1月以来,性能差异为irrelevant,可能更早:

Single quotes: 0.061846971511841 seconds
Double quotes: 0.061599016189575 seconds

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

  

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

(尽管文章引用了这句话,但最初的讽刺可能是attributed对温斯顿丘吉尔的错误{{3}},由Joseph Goebbels的宣传部门发明,将丘吉尔描绘成一个骗子:

  

Ich traue keiner Statistik,die ich nichtselbstgefälschthabe。

这松散地转化为“我不相信我没有假装自己的统计数据。”

答案 1 :(得分:43)

嗯,正如所有“现实生活中可能更快”的问题一样,你无法击败现实生活中的考验。

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很昂贵,内插器仍然必须这样做, 之后所有工作都要解析变量并修剪/复制原始字符串。

Somnath的更新:

我将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调试器来解析。我希望你明白我的观点。

答案 2 :(得分:23)

实时基准:

http://phpbench.com/

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

答案 3 :(得分:16)

使用@ Adam的测试

"these are " . $foo

请注意以下内容更快:

'these are ' . $foo;

这是因为有一个双引号“字符串”被评估,其中一个引用的'字符串'就是按原样...

答案 4 :(得分:11)

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

@uberfuzzy假设这只是一个关于语言细节的问题,我想它没关系。我只是试图在实际应用程序中添加单引号,双引号和heredoc之间的性能,与真实的性能接收器(如数据库查询不佳)相比毫无意义。

答案 5 :(得分:8)

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

请参阅

不要在这样的微优化上浪费时间。使用分析器在实际场景中测量应用程序的性能,然后优化实际需要的位置。与在代码中应用微优化相比,优化单个草率数据库查询可能会带来更大的性能提升。

答案 6 :(得分:3)

连接变量时会有区别......以及你对结果做了什么......如果你正在做的是将它转储到输出,是否输出缓冲。

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

$a = 'parse' . $this; 

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

$a = "parse $this";

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

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

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

答案 7 :(得分:3)

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

我现在似乎无法追踪到目前讨论的链接。

答案 8 :(得分:2)

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

'parse me '.$i.' times'

大于

"parse me $i times"

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

答案 9 :(得分:1)

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

$foo = "hello {$bar}";

$foo = "hello $bar";

并且这两个都比

$foo = 'hello' . $bar; 

答案 10 :(得分:1)

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

答案 11 :(得分: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 个测试用例都多次得到相同的结果,但连接仍然在性能上没有一点优势。

答案 12 :(得分:0)

应该注意的是,当使用带有3个变量的Adam Wright的示例的修改版本时,结果是相反的,前两个函数实际上更快,一致。这是使用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;&#39;而不只是整数3,但我得到了相同的结果。

$ bas = 3:

0.0016254
0.0015719
0.0019806

使用$ bas =&#39; 3&#39;:

0.0016495
0.0015608
0.0022755

应该注意的是,这些结果差别很大(我得到的变化约为300%),但平均值看起来相对稳定,并且几乎(10个案例中的9个)总是表现出更快的执行速度,使用方法2总是比方法1稍快。

总之:对于单个操作(插值或连接)而言,对于组合操作并不总是如此。

答案 13 :(得分: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中非常快,并且曾经使用 @Adam Wright <{1 / strong>。

答案 14 :(得分: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>";

== 我的结果:

array 获取 double 引用 2.1978828907013

数组获取引用2.0163490772247

数组集引用1.9173440933228

数组获取引用1.4982950687408

var set double 引用 1.485809803009

var set single 引用 1.3026781082153

== 我的结论!

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