English 中文(简体)
在PHP中,单引号和双引号之间是否有性能优势?[重复]
原标题:
  • 时间:2008-08-17 13:19:32
  •  标签:

考虑(假定为)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之间怎么样?

最佳回答

好的,和所有“现实生活中可能更快”的问题一样,你无法打败一次真实的测试。

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) . "
";
print timeFunc( Method2 , 10) . "
";
print timeFunc( Method3 , 10) . "
";

给它几次运行,以便将所有内容翻页,然后...

0.0035568 translates to 0.0035568. This number is already in decimal form and is the same in both English and Chinese.

0.0035388 translates to 0.0035388. This number is pronounced as líng diǎn líng sān wǔ sān bā.

0.0025394 translates to 0.0025394 in Chinese as there is no specific Chinese character for this number. It can be written as "零点零零二五三九四" in Chinese characters for clarity.

因此,正如预期的那样,插值几乎是相同的(噪声级别的差异,可能是由于插值引擎需要处理额外字符)。直接连接的速度约为66%,这并不令人惊讶。插值解析器将查找,找不到要做的事情,然后完成一个简单的内部字符串连接。即使连接很昂贵,插值器仍然必须在解析变量、修剪/复制原始字符串的所有工作之后这样做。

更新由索姆纳斯发布:

我在上述实时逻辑中添加了Method4()。

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

print timeFunc( Method4 , 10) . "
";

Results were:

0.0014739
0.0015574
0.0011955
0.001169

当您仅仅声明一个字符串而无需解析该字符串时,为什么要让PHP调试器进行解析,我希望您能理解我的意思。

问题回答

自2012年1月至今(甚至更早),性能差异已经变得不相关了。

Single quotes: 0.061846971511841 seconds
Double quotes: 0.061599016189575 seconds

之前的 PHP 版本可能存在差异 - 我个人更喜欢单引号而非双引号,因此这是一个方便的差异。文章的结论提出了一个很好的观点:

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

尽管文章引用了这句话,但原始的妙语很可能是错误地归属于温斯顿·丘吉尔,由约瑟夫·戈培尔的宣传部发明,旨在把丘吉尔描绘成一个说谎者。

我不相信任何我自己没有篡改的统计数据。

这个大致翻译为,“我不相信那些我没有伪造过的统计数据。”

实时基准测试:

将此翻译成中文:http://phpbench.com/ http://phpbench.com/

使用单引号与双引号连接变量时,实际上存在微小的差异。

@Adam的测试被用了

"these are " . $foo

请注意,以下更快:

 these are   . $foo;

这是因为双引号“string”会被计算,而单引号字符串则被视为原样...

不要过于纠结于尝试在PHP中优化字符串操作。如果您的数据库查询编写不良或未使用任何缓存方案,则串联与插值在真实世界性能上是无意义的。以这样的方式编写您的字符串操作,以便稍后调试代码变得容易,性能差异微不足道。

@uberfuzzy 假设这只是一个关于语言细节的问题,我想这没问题。我只是试图在对话中添加一些信息,比较单引号、双引号和heredoc在实际应用中的性能是无意义的,因为相比之下,实际性能的降低有更多原因,例如糟糕的数据库查询。

任何执行时间上的差异都是完全可以忽略的。

请看。

不要在微小的优化上浪费时间。使用分析工具来测试在真实场景中应用程序的性能,然后只在真正需要的地方进行优化。优化一个不规范的数据库查询可能会比在代码中应用微小优化技巧更有效提高性能。

连接变量时有所不同...以及您对结果所做的操作...以及如果您正在将其转储到输出中,则是否启用了输出缓冲。

另外,服务器的内存情况是什么样的?通常,在更高级别平台上的内存管理比低级平台上的要差...

$a =  parse  . $this; 

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

$a = "parse $this";

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

所以,相对于CPU而言,这些基准测试并不能完全反映实际情况。

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

我记得论坛软件Vanilla的开发人员将其代码中的所有双引号替换为单引号,并注意到了相当数量的性能提升。

我目前似乎找不到与讨论相关的链接。

只是为了添加一些内容到混合物中,如果在双引号字符串语法中使用变量:

$foo = "hello {$bar}";

比......更快

$foo = "hello $bar";

这两个都比...更快。

$foo =  hello  . $bar; 

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

 parse me  .$i.  times 

"parse me $i times"

虽然我会说第二个给你提供了更易读的代码。

实际上两者基本没有区别!请查看时间:http://micro-optimization.com/single-vs-double-quotes

应该注意到,当使用亚当•赖特的示例的修改版本带有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) . "
";
print timeFunc( Method2 , 10) . "
";
print timeFunc( Method3 , 10) . "
";

我也尝试用3个而不仅仅是整数3,但我得到了同样类型的结果。

带有$bas=3的

0.0016254
0.0015719
0.0019806

$bas = 3:转换为中文是“$bas等于3:”。

0.0016495
0.0015608
0.0022755

应该注意到,这些结果变化很大(我得到的变化大约为300%),但平均数看起来相对稳定,几乎(10个案例中有9个)总是表现出对前两种方法的更快执行,其中方法2始终比方法1略快。

总之:对于单个操作(无论是插值还是连接),适用的规律并不总是适用于组合操作。

是的,原本这是关于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提供。

我已经使用以下测试用例测试了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个测试用例都多次获得相同的结果,但串联在性能上仍然有一点优势。

根据@adam-wright的答案,我想知道是否在没有将字符串拼接/变量拼接到一起的情况下,会出现速度差异。

我的问题...

  • is $array[ key ] call or set faster than $array["key"] !?
  • is $var = "some text"; slower than $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() . "
<br>";
print getArrSplQuote() . "
<br>";
print setArrDblQuote() . "
<br>";
print setArrSplQuote() . "
<br>";
print setStrDblQuote() . "
<br>";
print setStrSplQuote() . "
<br>";

我的成绩:

数组获取双引号2.1978828907013。

数组获取单引号2.0163490772247

数组设置双引号1.9173440933228。

数组获取 '1.4982950687408'

变量集合 双引号 1.485809803009

变量设置单引号1.3026781082153

我的结论!

因此,结果是差异并不十分显著。但是在一个大项目中,我认为它可以起到关键作用!





相关问题
热门标签