测试环境:
| 
 1 
2 
3 
4 
 | 
    CPU : AMD Athlon(tm) II Dual-Core M300 × 2    OS  : ubuntu 12.04 32bit    PHP : PHP Version 5.3.10-1ubuntu3.10    tool: vld | 
代码1:
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
 | 
<?php$single_str = 'Hello quotes';$double_str = "Hello quotes";echo $single_str;echo $double_str;$tail = 'quotes';$single_str_tail = 'Hello '.$tail;$double_str_tail = "Hello ".$tail;echo $single_str_tail;echo $double_str_tail;$head = 'Hello';$single_str_head = $head.' quotes';$double_str_head = $head." quotes";echo $single_str_head;echo $double_str_head;?> | 
通过vld产生的结果如下
line     # *  op              fetch   ext  return  operands-------------------------------------------------------------   2     0  >   EXT_STMT                                      1      ASSIGN                               !0, 'Hello+quotes'   3     2      EXT_STMT                                      3      ASSIGN                               !1, 'Hello+quotes'   4     4      EXT_STMT                                      5      ECHO                                 !0   5     6      EXT_STMT                                      7      ECHO                                 !1   7     8      EXT_STMT                                      9      ASSIGN                               !2, 'quotes'   8    10      EXT_STMT                                     11      CONCAT                       ~3      'Hello+', !2        12      ASSIGN                               !3, ~3   9    13      EXT_STMT                                     14      CONCAT                       ~5      'Hello+', !2        15      ASSIGN                               !4, ~5  10    16      EXT_STMT                                     17      ECHO                                 !3  11    18      EXT_STMT                                     19      ECHO                                 !4  13    20      EXT_STMT                                     21      ASSIGN                               !5, 'Hello'  14    22      EXT_STMT                                     23      CONCAT                       ~8      !5, '+quotes'        24      ASSIGN                               !6, ~8  15    25      EXT_STMT                                     26      CONCAT                       ~10     !5, '+quotes'        27      ASSIGN                               !7, ~10  16    28      EXT_STMT                                     29      ECHO                                 !6  17    30      EXT_STMT                                     31      ECHO                                 !7  20    32      EXT_STMT                                     33    > RETURN                               1 | 
可以发现产生的opcode都是一样的,也就是单引号和双引号是一样的,但是我们改一下代码,把双引号的部分换一种写法,也就是把变量放在双引号里面,代码2:
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
 | 
<?php$single_str = 'Hello quotes';$double_str = "Hello quotes";echo $single_str;echo $double_str;$tail = 'quotes';$single_str_tail = 'Hello '.$tail;$double_str_tail = "Hello $tail";echo $single_str_tail;echo $double_str_tail;$head = 'Hello';$single_str_head = $head.' quotes';$double_str_head = "$head quotes";echo $single_str_head;echo $double_str_head;?> | 
产生的opcode如下:
line     # *  op              fetch   ext  return  operands-------------------------------------------------------------   2     0  >   EXT_STMT                                      1      ASSIGN                               !0, 'Hello+quotes'   3     2      EXT_STMT                                      3      ASSIGN                               !1, 'Hello+quotes'   4     4      EXT_STMT                                      5      ECHO                                 !0   5     6      EXT_STMT                                      7      ECHO                                 !1   7     8      EXT_STMT                                      9      ASSIGN                               !2, 'quotes'   8    10      EXT_STMT                                     11      CONCAT                       ~3      'Hello+', !2        12      ASSIGN                               !3, ~3   9    13      EXT_STMT                                     14      ADD_STRING                   ~5      'Hello+'        15      ADD_VAR                      ~5      ~5, !2        16      ASSIGN                               !4, ~5  10    17      EXT_STMT                                     18      ECHO                                 !3  11    19      EXT_STMT                                     20      ECHO                                 !4  13    21      EXT_STMT                                     22      ASSIGN                               !5, 'Hello'  14    23      EXT_STMT                                     24      CONCAT                       ~8      !5, '+quotes'        25      ASSIGN                               !6, ~8  15    26      EXT_STMT                                     27      ADD_VAR                      ~10     !5        28      ADD_STRING                   ~10     ~10, '+quotes'        29      ASSIGN                               !7, ~10  16    30      EXT_STMT                                     31      ECHO                                 !6  17    32      EXT_STMT                                     33      ECHO                                 !7  20    34      EXT_STMT                                     35    > RETURN                               1 | 
现在就能看出区别了,对比11,12以及14,15,16,或者24,25以及27,28,29,就可以发现使用单引号产生了CONCAT和ASSIGN两个动作,使用双引号产生了ADD_STRING,ADD_VAR,ASSIGN三个动作,貌似是单引号要快,因为少一个动作,但是我们还没测CONCAT 是否真的比ADD_STRING,ADD_VAR快,这个可以采用基准测试,或者直接查看对应的C函数代码比较得知。
总结: 采用代码1中的写法,单引号和双引号的作用是一样的,速度自然也是一样的,采用代码2中的写法,单引号和双引号产生的opcode不一样,虽然多双引号的opcode多一个动作,但是单从opcode还是无法判断单引号要比双引号要快,如果是这样的话后面还是需要其他的测试。
还有一种造成速度差异的是在分析语法和解释阶段,我看过的那片文章提到了这样一句话:"至于编译阶段,双引号和单引号的区别也是很大的, 我就举个数字来说明: 在scanning阶段, 对于双引号的词法规则有14条,而对于单引号,仅仅只有6条。"
如果是这样的话,说明双引号在解释编译阶段要慢,那是不是可以通过opcode缓存来消除差异?