最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 探究php in_array 的低性能

    正文概述 转载于:掘金(架构精进之路)   2021-08-26   222

    这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

    php 首要说的就是性能方面的提升。对于 in_array()一直诟病很多,至于性能有多差,先简单测试一下,看看数据。

    实例测试

    测试程序如下:

    <?php
    /**
     * 获取当前时间戳(毫秒级)
     * @return float
     */
    function microtime_float(){
        list($usec, $sec) = explode(' ', microtime());
        return ((float)$usec + (float)$sec);
    }
    
    /**
     * 数组初始化
     */
    $int_arr = $str_arr = [];
    for($i=0; $i<200000; $i++){
        $int_arr[] = $i;
        $str_arr[] = "{$i}";
    }
    
    $time_start = microtime_float();
    // 具体操作
    for($j=0; $j<3000; $j++){
        if(in_array(18000, $int_arr)){
            continue;
        }
    //    if(isset($int_arr[$key])){
    //        continue;
    //    }
    }
    
    $time_end = microtime_float();
    echo '消耗时间:'.($time_end - $time_start);
    

    测试结果

    in_array 方式

    1. 字符型字符串

    // 3k 消耗时间:1.0687351226807
    // 3w 消耗时间:10.569030046463
    

    2. int 型字符串

    // 3k 消耗时间:1.0500609874725
    // 3w 消耗时间:10.290988922119
    

    isset 方式

    1. 字符型字符串

    // 3k 消耗时间:0.00010299682617188
    // 3w 消耗时间:0.00089907646179199
    

    2. int 型字符串

    // 3k 消耗时间:0.00010108947753906
    // 3w 消耗时间:0.00085687637329102
    

    结合上面测试数据,两种方式的性能差距还是挺明显的。

    接着,我们利用 ltrace 来跟踪进程调用库函数的情况:

    $ ltrace -c /usr/local/php/bin/php test.php
    

    探究php in_array 的低性能

    看到库函数__strtol_internal 的调用非常之频繁,这个库函数__strtol_internal 是原来是 strtol 的别名,简单的说就是把字符串转换成长整形,可以推测 PHP 引擎已经检测到这是一个字符串型的数字,所以期望将他们转换成长整型来比较,这个转换过程中消耗了太多时间,我们再次执行:

    $ ltrace -e "__strtol_internal" /usr/local/php/bin/php test.php
    

    可以轻松抓到大量下图这样的调用,到此,问题找到了,in_array 这种松比较,会将两个字符型数字串先转换为长整型再进行比较,却不知性能就耗在这上面了。

    探究php in_array 的低性能

    知道了症结所在,我们解决的办法就很多了,最简单的就是为 in_array 加第三个参数为 true,即变为严格比较,同时还要比较类型,这样避免了 PHP 自作聪明的转换类型,跑起来果然快多了,代码如下:

    in_array(search,array,type)
    
    参考上例,改为如下:
    in_array(18000, $int_arr, true);
    in_array('18000', $str_arr, true);
    
    分别执行3k次的消耗时间分别为:0.88052606582642、0.88974308967591234
    

    总结

    总结一下,大数组的查询,用 in_array 函数是个糟糕的选择。应该尽量用 isset 函数来替代 。in_array 函数的复杂度是 O(n),而 isset 函数的复杂度是 O(1)。

    - END -

    Thanks for reading!


    起源地 » 探究php in_array 的低性能

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元