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

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

Speed difference in using inline strings vs concatenation in php5?

(假设php5)考虑

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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之间呢?


至少从2012年1月起,性能差异就没有关系了,并且可能更早:

1
2
Single quotes: 0.061846971511841 seconds
Double quotes: 0.061599016189575 seconds

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

Never trust a statistic you didn’t forge yourself.

(尽管文章引用了这个短语,但最初的讽刺可能是错误地归因于温斯顿·丘吉尔(Winston Churchill),这是约瑟夫·戈培尔(Joseph Goebbels)的宣传部将丘吉尔描绘成骗子的发明:

Ich traue keiner Statistik, die ich nicht selbst gef?lscht habe.

这大致可以解释为:"我不相信我没有伪造自己的统计数据。")


好吧,就像所有"现实生活中可能更快"的问题一样,您无法击败现实生活中的考验。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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

0.0035388

0.0025394

因此,正如预期的那样,插值实际上是相同的(噪声级别差异,可能是由于插值引擎需要处理的额外字符)。直接串联的速度约为速度的66%,这并不是很大的冲击。插值分析器将查找,无所事事,然后以简单的内部字符串concat完成。即使concat非常昂贵,在完成所有工作以解析出变量并修剪/复制原始字符串之后,插值器仍将必须这样做。

Somnath更新:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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调试器来解析。我希望你明白我的意思。


实时基准测试:

http://phpbench.com/

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


@Adam的测试使用

1
"these are" . $foo

请注意,以下速度更快:

1
'these are ' . $foo;

这是由于以下事实:对双引号的"字符串"进行了评估,其中单引号的"字符串"按原样被使用...


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

@uberfuzzy假设这只是有关语言细节的问题,我想这很好。我只是想增加一种对话,即与真实的性能接收器(例如不良的数据库查询)相比,在现实应用程序中比较单引号,双引号和heredoc之间的性能毫无意义。


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

请参见

  • NikiC的博客:颠覆单引号性能的神话,以技术性地解释内插和串联在PHP中的工作方式,以及为什么毫无意义地关心它们的速度。

不要在这种微优化上浪费时间。使用探查器在现实情况下测量应用程序的性能,然后优化实际需要的位置。与在整个代码中应用微优化相比,优化单个草率的数据库查询可能会带来更大的性能改进。


连接变量之间的区别...以及您对结果进行的操作...以及如果您正在执行的操作是将其转储到输出,则输出缓冲是否存在。

另外,服务器的内存状况如何?通常,较高级别平台上的内存管理要比较低平台上的内存管理差。

1
$a = 'parse' . $this;

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

1
$a ="parse $this";

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

因此,这些与CPU相关的基准测试无法说明全部情况。

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


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

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


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

1
'parse me '.$i.' times'

1
"parse me $i times"

尽管我会说第二个代码为您提供了更具可读性的代码。


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

1
$foo ="hello {$bar}";

比...快

1
$foo ="hello $bar";

而这两个都比

1
$foo = 'hello' . $bar;

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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';
    $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:

1
2
3
0.0016254
0.0015719
0.0019806

随着$ bas ='3':

1
2
3
0.0016495
0.0015608
0.0022755

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

结论:1个单一操作(插值或串联)的正确性对组合操作并不总是正确的。


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


推荐阅读