你知道怎么写出最快的循环么?
PHP中 $i++ 和 ++$i 的区别:
- 方式一:
-
- $begin = time();
- $i = 0;
- while(++$i < 10000)
- {
- $j = 0;
- while(++$j < 10000)
- ;
- ;
- }
- $end = time();
-
- 时间 : 16s
-
- 方式二:
-
- $begin = time();
- $i = 0;
- while($i < 10000)
- {
- $j = 0;
- while($j < 10000)
- ++$j;
- ++$i;
- }
- $end = time();
-
- 时间:13s
-
- 方式三:
-
- $begin = time();
- $i = 0;
- while($i < 10000)
- {
- $j = 0;
- while($j < 10000)
- $j++;
- $i++;
- }
- $end = time();
-
- 时间:15s
-
- 方式四:
-
- $begin = time();
- $i = 0;
- while($i++ < 10000)
- {
- $j = 0;
- while($j++ < 10000)
- ;
- ;
- }
- $end = time();
- 时间:13s
呵呵, 为什么会这样呢?
对比第一种方法和第二种方法, 因为在PHP中, 最终被执行的是OPCODE, 每行opline都有俩个操作数, 对于操作数来说, 一般有3种类型的存取方式, 临时变量, 变量, 和编译时变量, 这三种变量其中, 存取最快的是第三种, 编译器变量, 在OpCode执行过程中, 会讲一个变量的加一级引用存储在一个hash结构中, 用来加快存取速度.
在第一种方法中:
- $i = 0;
- while(++$i < 10000)
- {
- $j = 0;
- while(++$j < 10000)
- ;
- ;
- }
因为对于++$i来说, 我们需要得到它的返回值, 来和10000做比较, 这样就会使得PHP在编译的时候 , 生成一个变量(IS_VAR), 来保存自增的结果 , 也就是说, 这个时候用到了opline的return操作数.
然后, PHP会拿这个变量(IS_VAR)来和10000做比较.
而对于第二种方式:
- $i = 0;
- while($i < 10000)
- {
- $j = 0;
- while($j < 10000)
- ++$j;
- ++$i;
- }
这个过程中, $i已经优化成了编译变量(IS_CV), 而对于++$i, 因为我们不需要保存他的返回值, 所以也只是直接对编译变量进行自增..
也就是说, 方法一和方法二的速度差异, 就在于 对于方式二, 我们一直都在实用编译变量.. 编译变量的存取速度远快于变量(IS_VAR)
再来看第三种和第四种方式:
- $i = 0;
- while($i < 10000)
- {
- $j = 0;
- while($j < 10000)
- $j++;
- $i++;
- }
-
- $i = 0;
- while($i++ < 10000)
- {
- $j = 0;
- while($j++ < 10000)
- ;
- ;
- }
我们知道后缀自增(POST_INC), 会返回一个对原值的copy, 然后自增.
对于第四种方式, $i++以后, ZE会将$i的原值, 存储在一个临时变量(IS_TMP_VAR). 并且会拿这个临时变量和10000对比.
所以, 严格来讲, 这部分的速度比起第一种方式来说是会慢一些的.
而第三种方式慢在, 因为对$i++的返回值没有使用, 在语法分析阶段, $j++会归约成(rw_variable T_INC->expr_without_variable->expr, expr+’;’ => zend_do_free). 所以ZE就会安排一条opline, free掉这个临时变量…. (责任编辑:admin) |