• PHP 代码优化测试【Benchmark数据测试】


    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里

    Benchmark
    测试之前我们先来了解Benchmark。
    直接下载:http://pear.php.net/package/Benchmark/download
    Benchmark工具类包共有三个文件,分别是Timer.php、Iterate.php和Profiler.php,三个工具类功能相同,只是侧重点不同,都是用于调试代码获取程序的执行时间。
    1,Benchmark_Timer类原理与通过microtime函数获取微秒时间再比较前后两个时间值的差相同。
    2,Benchmark_Iterate类用于调试函数的平均执行时间。
    3,Benchmark_Profiler类用于统计代码和函数的执行时间以及函数的调用次数。
    我们用它来测试执行结果,使用它需要安装pear

    1) $row['id'] =0比 $row[id]=0 快,次数越大越明显/生产环境(Linux)下测试1个数量级;

    首先来测试直接写id的情况:

    error_reporting(E_ALL&~E_NOTICE );
    include "Benchmark/Timer.php";
    header("Content-type: text/html; charset=utf-8");
    
    require_once "Benchmark/Iterate.php";
    $bench = new Benchmark_Iterate;
    
    function test(){
        for($i = 0 ;$i < 100000; $i++){
            $arr[id] = 0;
        }
    }
    $bench->run(10,"test");
    echo '<pre>';
    print_r($bench->get());

    测试结果:

    Array
    (
        [1] => 0.140008
        [2] => 0.123007
        [3] => 0.117007
        [4] => 0.121007
        [5] => 0.114006
        [6] => 0.117007
        [7] => 0.112006
        [8] => 0.118007
        [9] => 0.114006
        [10] => 0.114007
        [mean] => 0.119006
        [iterations] => 10
    )

    而当我们把$arr[id] = 0; 改为

    $arr['id'] = 0

    测试结果为:

    Array
    (
        [1] => 0.007001
        [2] => 0.008000
        [3] => 0.007001
        [4] => 0.009000
        [5] => 0.008000
        [6] => 0.007001
        [7] => 0.013001
        [8] => 0.008000
        [9] => 0.008001
        [10] => 0.012000
        [mean] => 0.008700
        [iterations] => 10
    )

    可以看到,提升速度比较明显,因此,我们要规范数组的字段,不能写有风险的代码,$arr[id]这样子写有很大的风险。

    2) 递增(递减)一个预预定义的局部变量要比递增(递减)一个未定义的局部变量快;差别较大

    还是上述的代码,循环部分我们改为:

    $arr[$i]++;     //直接进行递增,没有预定义变量

    执行耗时为:

    Array
    (
        [1] => 0.011001
        [2] => 0.011001
        [3] => 0.012000
        [4] => 0.012001
        [5] => 0.011001
        [6] => 0.015000
        [7] => 0.013001
        [8] => 0.017001
        [9] => 0.011001
        [10] => 0.014001
        [mean] => 0.012700
        [iterations] => 10
    )

    而我们改为:

            $arr[$i] = 0;  //进行了预定义变量
            $arr[$i]++;    

    执行耗时:

    Array
    (
        [1] => 0.005000
        [2] => 0.003000
        [3] => 0.003001
        [4] => 0.003000
        [5] => 0.003000
        [6] => 0.003000
        [7] => 0.004000
        [8] => 0.003000
        [9] => 0.003001
        [10] => 0.004000
        [mean] => 0.003400
        [iterations] => 10
    )

    耗时缩减挺多

    3)在可行的情况下,避免使用正则表达式,str_replace 函数比 preg_replace,差别还是很明显的

    首先来看使用正则的情况下:

    error_reporting(E_ALL&~E_NOTICE );
    require_once "Benchmark/Iterate.php";
    $bench = new Benchmark_Iterate;
    $str = "2342674120840540640330461206579780032464020461647003497943133406004690797900978525820650";
    function test(){
        for($i = 0 ;$i < 10000; $i++){
            $str = preg_replace('/0/','a',$str);
        }
    }
    $bench->run(10,"test");
    echo '<pre>';
    print_r($bench->get());

    耗时:

    Array
    (
        [1] => 0.020001
        [2] => 0.019001
        [3] => 0.020001
        [4] => 0.017001
        [5] => 0.021001
        [6] => 0.019001
        [7] => 0.018001
        [8] => 0.017001
        [9] => 0.018001
        [10] => 0.021001
        [mean] => 0.019001
        [iterations] => 10
    )

    而使用:

    $str = str_replace('0','a',$str);

    耗时会减少挺多:

    Array
    (
        [1] => 0.006000
        [2] => 0.005000
        [3] => 0.005001
        [4] => 0.004000
        [5] => 0.004000
        [6] => 0.004000
        [7] => 0.004001
        [8] => 0.004000
        [9] => 0.004000
        [10] => 0.004000
        [mean] => 0.004400
        [iterations] => 10
    )

    同样我们可以延伸出,尽量使用php的函数去完成功能,那些函数底层c都是经过优化的,执行效率比较高。即:尽量采用PHP内置函数,且选择效率高的函数

    4)在有必要的时候使使用引用(&),测试差别较大,接近1个数量级

    引用的话,就不用像正常传递变量那样,复制多一个变量, 而是直接使用地址即可。

    我们先不用引用:

    error_reporting(E_ALL&~E_NOTICE );
    require_once "Benchmark/Iterate.php";
    $bench = new Benchmark_Iterate;
    $str = 'wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww';
    function setCon1($c){}
    
    function setCon2(&$c){}
    
    function test(){
        for($i = 0 ;$i < 10000; $i++){
            setCon1($str);   //这里使用setCon1,并没有用到引用
        }
    }
    $bench->run(10,"test");
    echo '<pre>';
    print_r($bench->get());

    耗时:

    Array
    (
        [1] => 0.017001
        [2] => 0.017001
        [3] => 0.017001
        [4] => 0.016001
        [5] => 0.017001
        [6] => 0.016001
        [7] => 0.013001
        [8] => 0.012000
        [9] => 0.011001
        [10] => 0.014001
        [mean] => 0.015000
        [iterations] => 10
    )

    而当我们在循环中改为:

    setCon2($str);

    耗时为:

    Array
    (
        [1] => 0.002001
        [2] => 0.001000
        [3] => 0.002000
        [4] => 0.002000
        [5] => 0.001000
        [6] => 0.004000
        [7] => 0.002000
        [8] => 0.002000
        [9] => 0.002000
        [10] => 0.001001
        [mean] => 0.001900
        [iterations] => 10
    )

    时间上缩小了很多。

    5 ) 判断字符串长度时,可用isset($str{15})代替strlen($str) < 15;因为isset()作为一种语言结构,而strlen()是函数,语言结构快于函数

     使用strlen($str)函数来判断,代码如下:

    error_reporting(E_ALL&~E_NOTICE );
    
    require_once "Benchmark/Iterate.php";
    $bench = new Benchmark_Iterate;
    
    function test(){
        $str = "Hello World";
        for($i = 0 ;$i < 10000; $i++){
            strlen($str) < 15;
        }
    }
    
    $bench->run(10,"test");
    echo '<pre>';
    print_r($bench->get());

    执行耗时:

    Array
    (
        [1] => 0.202800
        [2] => 0.140400
        [3] => 0.156001
        [4] => 0.140400
        [5] => 0.140400
        [6] => 0.156000
        [7] => 0.140401
        [8] => 0.140400
        [9] => 0.156000
        [10] => 0.140400
        [mean] => 0.151320
        [iterations] => 10
    )

    而当我们使用

    isset($str[4]);

    判断,将会加快很多,执行耗时:

    Array
    (
        [1] => 0.000000
        [2] => 0.000000
        [3] => 0.000000
        [4] => 0.000000
        [5] => 0.000000
        [6] => 0.000000
        [7] => 0.015600
        [8] => 0.000000
        [9] => 0.000000
        [10] => 0.000000
        [mean] => 0.001560
        [iterations] => 10
    )

     6 ) $_SERVER['DOCUMENT_ROOT']代替str_replace('//','/',dirname(__FILE__) .'/') ; wamp测试无太大差别/Linux生产环境测试性能提升 500% (5倍)

    首先我们先用 $path = str_replace('//','/',dirname(__FILE__) .'/'); 测试:

    error_reporting(E_ALL&~E_NOTICE );
    
    require_once "Benchmark/Iterate.php";
    $bench = new Benchmark_Iterate;
    
    function test(){
        for($i = 0 ;$i < 10000; $i++){
            $path = str_replace('//','/',dirname(__FILE__) .'/'); 
        }
    }
    
    $bench->run(10,"test");
    echo '<pre>';
    print_r($bench->get());

    执行耗时:

    Array
    (
        [1] => 0.320001
        [2] => 0.320000
        [3] => 0.320000
        [4] => 0.312002
        [5] => 0.322002
        [6] => 0.310000
        [7] => 0.310001
        [8] => 0.312006
        [9] => 0.322003
        [10] => 0.312002
        [mean] => 0.316001
        [iterations] => 10
    )

    当改为:

    $path = $_SERVER['DOCUMENT_ROOT'];

    执行耗时:

    Array
    (
        [1] => 0.000000
        [2] => 0.010000
        [3] => 0.000000
        [4] => 0.000000
        [5] => 0.010000
        [6] => 0.000000
        [7] => 0.000000
        [8] => 0.010000
        [9] => 0.000000
        [10] => 0.000000
        [mean] => 0.003000
        [iterations] => 10
    )

    几乎不在毫秒级别内。耗时少很多。

     7 ) 获取Unix时间戳时用$_SERVER['REQUEST_TIME'] 代替time(); 测试性能提升很多

    首先我们使用time() 来获取:

    error_reporting(E_ALL&~E_NOTICE );
    
    require_once "Benchmark/Iterate.php";
    $bench = new Benchmark_Iterate;
    
    function test(){
        for($i = 0 ;$i < 10000; $i++){
            $time = time();
        }
    }
    
    $bench->run(10,"test");
    echo '<pre>';
    print_r($bench->get());

    执行耗时:

    Array
    (
        [1] => 0.170001
        [2] => 0.150000
        [3] => 0.150000
        [4] => 0.150000
        [5] => 0.150001
        [6] => 0.150000
        [7] => 0.150000
        [8] => 0.150000
        [9] => 0.150000
        [10] => 0.160001
        [mean] => 0.153000
        [iterations] => 10
    )

    而改为:

    $time =  $_SERVER['REQUEST_TIME'];

    的时候,执行耗时减少很多:

    Array
    (
        [1] => 0.000000
        [2] => 0.000000
        [3] => 0.010001
        [4] => 0.000000
        [5] => 0.000000
        [6] => 0.000000
        [7] => 0.000000
        [8] => 0.010000
        [9] => 0.000000
        [10] => 0.000000
        [mean] => 0.002000
        [iterations] => 10
    )

    几乎不在毫秒级别内

    其实还有很多其他的各种优化小细节,例如:

    * foreach函数,没有用到键的时候,就不要加键。

    * include 文件时尽量使用绝对路径,因为它避免了 PHP 去 include_path 里查找文件的速 度,解析操作系统路径所需的时间会更少。【测试差别其实不明显

    * 用单引号(’’)代替双引号(””),单引号为强类型,将其中的所以字符都认作字符,而双引号的为弱类型,它会检测其中是否存在变量 【测试差别不大,但是用双引号有风险

    * Apache 处理 PHP 脚本的速度要比静态页面慢 2-10 倍,因此尽量采用多的静态页面,少的脚本;PHP程序使用文件缓存性能会倍增【不用测试我们也知道,测试速度快很多】;

    * 一般不建议启用auto_start(session.auto_start:是否自动启用) ,因为创建Session需要消耗系统资源,我们通常只会在需要用到Sesson时,才会使用session_start函数来开启Session功能。

    优化无止境.............................................................

  • 相关阅读:
    LG5283 异或粽子
    LG2216 理想的正方形
    LG1484 种树
    洛谷3721 HNOI2017单旋(LCT+set+思维)
    洛谷3348 大森林 (LCT + 虚点 + 树上差分)
    CF1082E Increasing Frequency (multiset+乱搞+贪心)
    CF1082G Petya and Graph(最小割,最大权闭合子图)
    cf1082D Maximum Diameter Graph(构造+模拟+细节)
    洛谷3320 SDOI2015寻宝游戏(set+dfs序)(反向迭代器的注意事项!)
    CF613D Kingdom and its Cities(虚树+贪心)
  • 原文地址:https://www.cnblogs.com/zhenghongxin/p/7401689.html
Copyright © 2020-2023  润新知