测试环境:
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缓存来消除差异?