<?php
require_once(‘Benchmark/Iterate.php‘);
$benchmark = new Benchmark_Iterate();
$benchmark->run(10, ‘myFunction‘,‘test‘);
$result = $benchmark->get();
echo "
"; print_r($result); echo "
";
exit;
function myFunction($var) {
// do something
echo ‘Hello ‘;
}
?>
Array(
[1] => 0.000427
[2] => 0.000079
[3] => 0.000072
[4] => 0.000071
[5] => 0.000076
[6] => 0.000070
[7] => 0.000073
[8] => 0.000070
[9] => 0.000074
[10] => 0.000072
[mean] => 0.000108
[iterations] => 10
)
myFunction的每次執(zhí)行,benchmark對(duì)象都會(huì)跟蹤執(zhí)行時(shí)間。并且會(huì)計(jì)算平均的執(zhí)行時(shí)間([mean]那一行)。通過(guò)多次運(yùn)行目標(biāo)函數(shù),你可以得到該函數(shù)的平均運(yùn)行時(shí)間。 在實(shí)際測(cè)試中,函數(shù)的次數(shù)應(yīng)當(dāng)至少1000次左右,這樣可以得到較客觀的結(jié)果。 現(xiàn)在我們看看另一個(gè)測(cè)試腳本運(yùn)行時(shí)間的方法--使用Benchmark_Timer類來(lái)測(cè)試一段代碼執(zhí)行所消耗的時(shí)間及這一段代碼中每次調(diào)用與下一次調(diào)用間的時(shí)間。 benchmark2.php
<?php
require_once ‘Benchmark/Timer.php‘;
$timer = new Benchmark_Timer();
$timer->start();
$timer->setMarker(‘start_myFunction‘);
for($i=0; $i<10; $i++){
myFunction($argument);
}
$timer->setMarker(‘end_myFunction‘);
$timer->stop();
$profiling = $timer->getProfiling();
echo ‘
Time elapsed: ‘ .
$timer->timeElapsed(‘start_myFunction‘,‘end_myFunction‘) .‘
‘;
echo ‘
‘; print_r($profiling); echo ‘
‘;
exit;
function myFunction($var) {
static $counter = 0;
// do something
echo $counter++ . ‘ ‘;
}
?>
首先,建立一個(gè)benchmark timer對(duì)象$timer。然后調(diào)用start()方法,表示開(kāi)始計(jì)時(shí)。 SetMaker()方法用來(lái)標(biāo)記要測(cè)試的代碼段。MyFunction()函數(shù)在循環(huán)中被調(diào)用,表示一段要執(zhí)行的代碼(當(dāng)然實(shí)際中不會(huì)這么簡(jiǎn)單)。然后再用$timer對(duì)象的setMarker()方法標(biāo)記程序執(zhí)行終點(diǎn)。分析信息用getProfiling()來(lái)獲取。在兩個(gè)標(biāo)記間程序執(zhí)行消耗的時(shí)間用timeElapsed()方法計(jì)算出來(lái)(就像例子中的循環(huán))。最后,用print_r()輸出信息到屏幕:
Array
(
[0] => Array
(
[name] => Start
[time] => 1085730111.27175200
[diff] => -
[total] => 1085730111.271752
)
[1] => Array
(
[name] => start_myFunction
[time] => 1085730111.27203800
[diff] => 0.000286
[total] => 1085730111.272038
)
[2] => Array
(
[name] => end_myFunction
[time] => 1085730111.27263200
[diff] => 0.000594
[total] => 1085730111.272632
)
[3] => Array
(
[name] => Stop
[time] => 1085730111.27271800
[diff] => 0.000086
[total] => 1085730111.272718
)
)
0 1 2 3 4 5 6 7 8 9 Time elapsed: 0.000594 通過(guò)這種方法,你可以在代碼中設(shè)置大量時(shí)間段標(biāo)記,獲取每段代碼執(zhí)行時(shí)消耗的時(shí)間,很容易可以看出到底是哪一部份的代碼影響了整個(gè)程序的運(yùn)行效率。然后開(kāi)始著手對(duì)這部份代碼進(jìn)行改進(jìn)。 用以上兩種方法,你可以找出代碼中最影響速度的部份代碼。另外還可以用來(lái)對(duì)優(yōu)化后的代碼進(jìn)行測(cè)試,看看到底執(zhí)行速度提高了多少。通過(guò)測(cè)試->優(yōu)化->測(cè)試->優(yōu)化 …這樣不斷循環(huán),你可以最終確定提供最佳效率的代碼。
badloops.php <?php
require_once(‘Benchmark/Iterate.php‘);
define(‘MAX_RUN‘,100);
$data = array(1, 2, 3, 4, 5);
doBenchmark(‘v1‘, $data);
doBenchmark(‘v2‘, $data);
doBenchmark(‘v3‘, $data);
function doBenchmark($functionName = null, $arr = null)
{
reset($arr);
$benchmark = new Benchmark_Iterate;
$benchmark->run(MAX_RUN, $functionName, $arr);
$result = $benchmark->get();
echo ‘<br>‘;
printf("%s ran %d times where average exec time %.5f ms",$functionName,$result[‘iterations‘],$result[‘mean‘] * 1000);
}
function v1($myArray = null) {
// 效率很差的循環(huán)
for ($i =0; $i < sizeof($myArray); $i++)
{
echo ‘<!--‘ . $myArray[$i] . ‘ --> ‘;
}
}
function v2($myArray = null) {
// 效率略有提高
$max = sizeof($myArray);
for ($i =0; $i < $max ; $i++)
{
echo ‘<!--‘ . $myArray[$i] . ‘ --> ‘;
}
}
function v3($myArray = null){
//最佳效率
echo "<!--", implode(" --> <!--", $myArray), " --> ";
}
?>
?>
<?php
if(ereg(‘gzip‘,$_SERVER[‘HTTP_ACCEPT_ENCODING‘])) {
//瀏覽器支持
} else {
//瀏覽器不支持,輸出其它內(nèi)容
}
?>
接下來(lái)我們對(duì)上面這個(gè)PHP程序進(jìn)行擴(kuò)展,使用
ob_start(ob_gzhandler)來(lái)將網(wǎng)頁(yè)內(nèi)容壓縮,存入緩沖并發(fā)送給支持gzip的瀏覽器,瀏覽器會(huì)自動(dòng)將壓縮后的內(nèi)容解壓,顯示。
<?php
define(‘MAX‘,100);
if(ereg(‘gzip‘,$_SERVER[‘HTTP_ACCEPT_ENCODING‘]))
{
//瀏覽器支持gzip,將內(nèi)容壓縮并緩沖輸出
ob_start("ob_gzhandler");
$output = ‘‘;
for($i=0;$i<=MAX;$i++)
{
$output .= "This is line $i
";
}
echo "瀏覽器支持gzip壓縮輸出
";
echo $output;
}
else
{
//瀏覽器不支持,直接輸出
for($i=0;$i<=MAX;$i++)
{
$output .= "This is line $i
";
}
echo "瀏覽器不支持gzip壓縮輸出
";
echo $output;
}
?>
使用gzip壓縮生成的網(wǎng)頁(yè)的HTTP頭信息與一般的網(wǎng)頁(yè)相比中會(huì)多出這樣的信息:
Content-Encoding: gzipContent-Length: 270 如果你想得到更詳細(xì)的信息,請(qǐng)參看mod_gzip項(xiàng)目主頁(yè): 類似地,我們也可以利用mod_deflate,壓縮率比mod_gzip略低一些。調(diào)用zip函數(shù)需要耗用服務(wù)器內(nèi)存,所以要慎用,視需求而定。
PEAR除了可以對(duì)輸出的內(nèi)容進(jìn)行緩存處理外,還可以將對(duì)某個(gè)函數(shù)的調(diào)用結(jié)果緩存起來(lái)。這是個(gè)很有趣的功能,如果你的程序要頻繁使用到某個(gè)函數(shù),而且調(diào)用的結(jié)果相同的話,我建議你不妨試試,特別是當(dāng)這個(gè)函數(shù)運(yùn)行起來(lái)比較慢的時(shí)候。
聯(lián)系客服