微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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{

}

I would like to kNow what is happening under-the-hood.

平均速度:

>针执行时间:0.054877042770386秒
>如果执行时间:0.014014959335327秒
>开关执行时间:0.0093550682067871秒

解决方法:

使用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

针和草垛

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

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

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

一点比较

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

如果语句使用IS_EQUAL,这与case类似,但第二个值必须是常量.我认为这会减慢检查速度,因为现在有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 =’不匹配’;

Switch took 0.52629804611206
if took 0.40276217460632
needle haystack took 1.6838929653168

我不确定你使用了什么输入,但是对于我来说是否和切换类似(为了更易读,切换边缘)

编辑:

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

这将使用IS_IDENTICAL替换IS_EQUAL调用

有一点点加速

适用于所有测试用例

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 =’不匹配’;

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐