1. 程式人生 > >PHP 代碼優化測試【Benchmark數據測試】

PHP 代碼優化測試【Benchmark數據測試】

replace time函數 for doc 內置 建議 操作 __file__ iter

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 ) 獲取Unix時間戳時用$_SERVER[‘REQUEST_TIME‘] 代替time(); 測試性能提升很多

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

幾乎不在毫秒級別內。耗時少很多。

其實還有很多其他的各種優化小細節,例如:

* foreach函數,沒有用到鍵的時候,就不要加鍵。

* include 文件時盡量使用絕對路徑,因為它避免了 PHP 去 include_path 裏查找文件的速 度,解析操作系統路徑所需的時間會更少。【測試差別其實不明顯

* 用單引號(’’)代替雙引號(””),單引號為強類型,將其中的所以字符都認作字符,而雙引號的為弱類型,它會檢測其中是否存在變量 【測試差別不大,但是用雙引號有風險

* 判斷字符串長度時,可用isset($str{15})代替strlen($str) < 15;因為isset()作為一種語言結構,而strlen()是函數,語言結構快於函數

* Apache 處理 PHP 腳本的速度要比靜態頁面慢 2-10 倍,因此盡量采用多的靜態頁面,少的腳本;PHP程序使用文件緩存性能會倍增【不用測試我們也知道,測試速度快很多】;

* 一般不建議啟用auto_start(session.auto_start:是否自動啟用) ,因為創建Session需要消耗系統資源,我們通常只會在需要用到Sesson時,才會使用session_start函數來開啟Session功能。

優化無止境.............................................................

PHP 代碼優化測試【Benchmark數據測試】