在这些条件下发生了什么?

时间:2015-09-17 18:46:06

标签: php

使用开关:

switch($page){
    case 'dog':
    case 'cat':
    case 'robot':
    case 'default':{

        break;
    };
    default:{

        break;
    }
}

使用if:

if($page == 'dog' || $page == 'cat' || $page == 'robot' || $page == 'default'){

}else{

}

使用针和&干草堆:

$pages = array('dog', 'cat', 'robot', 'default');
if(in_array($page, $pages)){

}else{

}
  

我想知道幕后发生了什么。

平均速度:

  • 执行时间:0.054877042770386秒
  • 如果执行时间:0.014014959335327秒
  • 切换执行时间:0.0093550682067871秒

1 个答案:

答案 0 :(得分:4)

使用VLD输出的所有方案(PHP 5.6.4)

<强>开关

number of ops:  31
compiled vars:  !0 = $page
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   EXT_STMT                                                 
         1        ASSIGN                                                   !0, 'default'
   3     2        NOP                                                      
   4     3        EXT_STMT                                                 
         4        CASE                                             ~1      !0, 'dog'
         5      > JMPZ                                                     ~1, ->7
   5     6    > > JMP                                                      ->10
         7    >   EXT_STMT                                                 
         8        CASE                                             ~1      !0, 'cat'
         9      > JMPZ                                                     ~1, ->11
   6    10    > > JMP                                                      ->14
        11    >   EXT_STMT                                                 
        12        CASE                                             ~1      !0, 'robot'
        13      > JMPZ                                                     ~1, ->15
   7    14    > > JMP                                                      ->18
        15    >   EXT_STMT                                                 
        16        CASE                                             ~1      !0, 'default'
        17      > JMPZ                                                     ~1, ->23
        18    >   NOP                                                      
   9    19        EXT_STMT                                                 
        20      > BRK                                                      1, ->30
  11    21*       EXT_STMT                                                 
        22*       JMP                                                      ->25
        23    >   EXT_STMT                                                 
        24      > JMP                                                      ->29
        25    >   NOP                                                      
  13    26        EXT_STMT                                                 
        27      > BRK                                                      1, ->30
  15    28*       JMP                                                      ->30
        29    > > JMP                                                      ->25
  16    30    > > RETURN                                                   1

如果

number of ops:  16
compiled vars:  !0 = $page
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   EXT_STMT                                                 
         1        ASSIGN                                                   !0, 'default'
   3     2        EXT_STMT                                                 
         3        IS_EQUAL                                         ~1      !0, 'dog'
         4      > JMPNZ_EX                                         ~1      ~1, ->7
         5    >   IS_EQUAL                                         ~2      !0, 'cat'
         6        BOOL                                             ~1      ~2
         7    > > JMPNZ_EX                                         ~1      ~1, ->10
         8    >   IS_EQUAL                                         ~3      !0, 'robot'
         9        BOOL                                             ~1      ~3
        10    > > JMPNZ_EX                                         ~1      ~1, ->13
        11    >   IS_EQUAL                                         ~4      !0, 'default'
        12        BOOL                                             ~1      ~4
        13    > > JMPZ                                                     ~1, ->15
   5    14    > > JMP                                                      ->15

针和&amp;草堆

number of ops:  17
compiled vars:  !0 = $page, !1 = $pages
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   EXT_STMT                                                 
         1        ASSIGN                                                   !0, 'default'
   3     2        EXT_STMT                                                 
         3        INIT_ARRAY                                       ~1      'dog'
         4        ADD_ARRAY_ELEMENT                                ~1      'cat'
         5        ADD_ARRAY_ELEMENT                                ~1      'robot'
         6        ADD_ARRAY_ELEMENT                                ~1      'default'
         7        ASSIGN                                                   !1, ~1
   4     8        EXT_STMT                                                 
         9        EXT_FCALL_BEGIN                                          
        10        SEND_VAR                                                 !0
        11        SEND_VAR                                                 !1
        12        DO_FCALL                                      2  $3      'in_array'
        13        EXT_FCALL_END                                            
        14      > JMPZ                                                     $3, ->16
   6    15    > > JMP                                                      ->16
   9    16    > > RETURN                                                   1

正如您所看到的那样,交换机实际上拥有最多的操作,但是在您的测试用例中是最快的(有兴趣看到它,因为我想这些方法中的每一种都可以是某种情况下的“最佳”)< / p>

虽然操作不是标准的工作量,但它们确实给出了指示。

稍微比较

Switch使用了很多CASE(检查2个值相等)和JMPZ(如果地址为零则跳转)。

如果语句使用IS_EQUAL,这与大小写类似,但第二个值必须是常量。我认为这会减慢检查速度,因为现在有2个变量可以检查。 (您的基准测试结果似乎与此一致)

下一个使用函数调用。 PHP中的函数通常被认为很慢 https://github.com/php/php-src/blob/df29df7ec40cf7950a98f36bfa99ef19f0950309/ext/standard/array.c#L1595

是函数的C源,每种类型的变量都有不同的逻辑。假设我们使用字符串,则循环数组并使用

检查每个值

https://github.com/php/php-src/blob/213b49620d24ebebe3cf19787ee6e3448d27d046/Zend/zend_operators.h#L712

尽可能早退。

基准脚本

$max_checks = 1000000;

$bench = -microtime(true);
for($i = 0;$i < $max_checks; $i++) {
  switch($page){
    case 'dog':
    case 'cat':
    case 'robot':
    case 'default':{
       break;
     };
    default:{

      break;
    }
  }
}
echo "\nSwitch took " . (microtime(true) + $bench);

$bench = -microtime(true);


for($i = 0;$i < $max_checks; $i++) {
  $page == 'dog' || $page == 'cat' || $page == 'robot' || $page == 'default';
}
echo "\nif took " . (microtime(true) + $bench);


$pages = array('dog', 'cat', 'robot', 'default');

$bench = -microtime(true);
for($i = 0;$i < $max_checks; $i++) {
  (in_array($page, $pages));
}

echo "\nneedle haystack took " . (microtime(true) + $bench);

传入$page = 'dog';

Switch took 0.31698203086853
if took 0.18721604347229
needle haystack took 1.5701420307159

传递$page = 'default';

Switch took 0.46866297721863
if took 0.40072298049927
needle haystack took 1.6747360229492

传递$page = 'no match';

Switch took 0.52629804611206
if took 0.40276217460632
needle haystack took 1.6838929653168

我不确定你使用了什么输入,但是对于我而言切换是否相似(切换边缘以便更具可读性)

编辑:

另外1个更快的测试用例。 使用if ===

这会使用IS_EQUAL

替换IS_IDENTICAL次来电

有一点点加速

适用于所有测试用例

if      took 0.43217587471008
if(===) took 0.39284706115723

操作码列表 http://php.net/manual/en/internals2.opcodes.list.php

修改数字2

因为我无论如何都在测试PHP 7 RC3。

重新运行基准(在同一台机器上)

$page = 'dog';

Switch took 0.018393993377686
if took 0.030646085739136
if(===) took 0.036449909210205
needle haystack took 0.045974969863892

$page = 'default';

Switch took 0.040921211242676
if took 0.085216999053955
if(===) took 0.1043848991394
needle haystack took 0.052649974822998

$page = 'no match';

Switch took 0.059795141220093
if took 0.080615997314453
if(===) took 0.10486197471619
needle haystack took 0.049200057983398

使用PHP 7,针和干草堆看起来最好