當前位置:編程學習大全網 - 源碼下載 - php ob_start提高多少速度

php ob_start提高多少速度

由於PHP是“壹邊編譯壹邊執行”的腳本語言,某種程度上也提供了壹種相當方便的結果集緩存使用方法—通過動態include相應的數據定義代碼段的方式使用緩存。

近來做了壹陣子程序性能的優化工作,有個比較有意思的想法,想提出來和大家交流壹下。

Cache是“以空間換時間”策略的典型應用模式,是提高系統性能的壹種重要方法。緩存的使用在大訪問量的情況下能夠極大的減少對數據庫操作的次數,明顯降低系統負荷提高系統性能。相比頁面的緩存,結果集是壹種“原始數據”不包含格式信息,數據量相對較小,而且可以再進行格式化,所以顯得相當靈活。由於PHP是“壹邊編譯壹邊執行”的腳本語言,某種程度上也提供了壹種相當方便的結果集緩存使用方法——通過動態include相應的數據定義代碼段的方式使用緩存。如果在“RamDisk”上建緩存的話,效率應該還可以得到進壹步的提升。以下是壹小段示例代碼,供參考。

// load data with cache

function

load_data($id,$cache_lifetime) {

// the return data

$data =

array();

// make cache filename

$cache_filename =

‘cache_‘.$id.‘.php‘;

// check cache file‘s last modify time

$cache_filetime = filemtime($cache_filename);

if (time() -

$cache_filetime <= $cache_lifetime) {

//** the cache is not expire

include($cache_filename);

} else {

//** the cache is

expired

// load data from database

// ...

while

($dbo->nextRecord()) {

// $data[] = ...

}

// format

the data as a php file

$data_cache = "

while (list($key, $val) =

each($data)) {

$data_cache .= "\$data[‘$key‘]=array(‘";

$data_cache .= "‘NAME‘=>\"".qoute($val[‘NAME‘])."\","

$data_cache .= "‘VALUE‘=>\"".qoute($val[‘VALUE‘])."\""

$data_cache .= ";);\r\n";

}

$data_cache = "?>\r\n";

// save the data to the cache file

if ($fd =

fopen($cache_filename,‘w+‘)) {

fputs($fd,$data_cache);

fclose($fd);

}

}

return $data;

}

> 適用情況:

1.數據相對比較穩定,主要是讀取操作。

2.文件操作要比數據庫操作快。

3.復雜數據訪問,大數據量訪問,密集數據訪問,系統數據庫負載極重。

4.Web/DB分離結構或者多Web單DB結構。

未經證實的問題:

1.並發訪問時對文件的讀寫是否會引起鎖定問題。

2.涉及到的數據文件太多時,性能如何。

擴展思路:

1.生成JavaScript數據定義代碼,在客戶端調用。

2.還未想到……

望***同探討。

緩存

如果妳想要讓自己龐大的PHP應用有更好的性能表現,采用緩存也是壹種很好的方法。現在已經有許多緩存方案可供選擇,其中包括:Zend

Cache,APC,和Afterburner Cache。

所有這些產品都屬於“緩存模塊”。當第壹次出現對.php文件的請求時,它們會在Web服務器內存中保存PHP的中間代碼,此後就用“經過編譯”的版本響應後繼的請求。這種方法確實能夠改善應用的性能,因為它使得磁盤訪問量減低到了最少的程度(代碼已經讀取和解析),代碼直接在內存中運行使得服務器響應請求的速度大大提高。當然,緩存模塊還會監視PHP源文件的變化,必要時重新緩存頁面,從而防止了用戶得到的頁面仍舊由過時的PHP代碼生成。由於緩存模塊能夠明顯地降低服務器的負載、提高PHP應用的響應效率,因此它們非常適合於負載較大的網站使用。

如何選擇這些緩存產品

Zend Cache是Zend Technologies公司的商業軟件,而Zend

Technologies就是前面提到的那個為我們提供PHP引擎和免費Zend Optimizer的公司。Zend

Cache確實是名不虛傳!對於大型的PHP頁面,妳可以感覺到第壹次運行之後速度就會有所提高,而且服務器也會有更多的可用資源。遺憾的是這個產品並不免費,不過在有些情形下它仍舊是物超所值。

Afterburner Cache是來自Bware Technologies的免費緩存模塊,當前這個產品還是Beta版。Afterburner

Cache的做法看起來與Zend Cache差不多,但它對性能的改善程度(還)不能與Zend Cache相比,而且它還不能與Zend

Optimizer壹起工作。

APC是Alternative PHP Cache的縮寫,它是來自Community

Connect的又壹個免費緩存模塊。這個產品已經具有足夠的穩定性供正式場合使用,而且它看起來也能在很大程度上提高響應請求的速度。

有關壓縮

來自Remote

Communications的免費Apache模塊mod_gzip就具有為支持這類內容編碼的瀏覽器壓縮靜態Web內容的能力。對於絕大多數靜態Web內容,mod_gzip都非常有效。mod_gzip可以方便地編譯到Apache裏面,也可以作為DSO使用。據Remote

communications公司說,mod_gzip也能夠壓縮來自mod_php、mod_perl等的動態內容。我試了壹次又壹次,但看來還是不行。我看了許多關於mod_gzip的論壇和文章,看來到了mod_gzip的下壹個版本(可能是1.3.14.6f)這個問題有望得到解決。在此之前,我們可以在網站的靜態部分使用mod_gzip。

然而有時我們確實蹊要壓縮動態內容,所以必須找找其他辦法。有壹種辦法是使用class.gzip_encode.php,這是壹個可以用來壓縮頁面內容的PHP類,具體方法是在PHP腳本的開頭和末尾調用該類的某些函數。如果要在網站級實現這個方案,可以從php.ini文件的auto_prepend以及auto_append指令調用這些函數。這種方法雖然有效,但它無疑為高負載的網站帶來了更多的開銷。關於如何使用這個類的詳細說明,請參見它的源代碼。它的源代碼說明相當完善,作者告訴了妳所有妳必須知道的事情。

PHP

4.0.4有壹個新的輸出緩存句柄ob_gzhandler,它與前面的類相似,但用法不同。使用ob_gzhandler時要在php.ini中加入的內容如下:

output_handler = ob_gzhandler

這行代碼使得PHP激活輸出緩存,並壓縮它發送出去的所有內容。如果由於某種原因妳不想在php.ini中加上這行代碼,妳還可以通過PHP源文件所在目錄的.htaccess文件改變默認的服務器行為(不壓縮),語法如下:

php_value

output_handler ob_gzhandler

或者是從PHP代碼調用,如下所示:

ob_start("ob_gzhandler");

采用輸出緩存句柄的方法確實非常有效,而且不會給服務器帶來什麽特殊的負荷。但必須註意的是,Netscape

Communicator對壓縮圖形的支持不佳,因此除非妳能夠保證所有用戶都使用IE瀏覽器,否則妳應該禁止壓縮JPEG和GIF圖形。壹般地,對於所有其他文件,這種壓縮都有效,但建議妳針對各種瀏覽器都分別進行測試,特別是當妳使用了特殊的插件或者數據查看器時這壹點尤其重要。

閱讀提示:PEAR 的緩沖包提供了緩沖動態內容,數據庫查詢和 PHP 函數調用的框架。本文介紹如何采用 PEAR 來緩沖 PHP 程序

采用 PEAR 來緩沖 PHP 程序

PHP 世界中緩沖是壹個熱門的話題,因為 PHP 產生的動態頁面,每次用戶請求都需要重新計算,不論請求的結果是否壹樣,同時,PHP

每次都會編譯壹次腳本。這樣的超負荷運轉對壹個流量很高的網站來說肯定難以忍受。幸運的是, Web 的結果可以緩沖,而不需要重新運行和編譯腳本,商品化的產品像

ZendCache 或者開源的 Alternate PHP Cache都提供了把 PHP 腳本編譯為字節代碼並緩沖的辦法。

PEAR

的緩沖包提供了緩沖動態內容,數據庫查詢和 PHP 函數調用的框架。

就像 Perl 有 CPAN, TeX 有 CTAN,PHP

也有自己的中心資源庫,存放類,庫和模塊。這個庫稱為 PEAR(PHP Extension and Add-On

Repository)。

本文假設妳已經安裝了 PEAR 環境,如果沒有的話,可以去 PHP 網站下載。PEAR

的緩沖包包含壹個總體的緩沖類和幾個特別的子類。緩沖類使用容器類來存貯和管理緩沖數據。

下面是 PEAR

緩沖當前所包含的容器,以及各自的參數:

file -- file 容器在文件系統存儲了緩沖的數據,是最快的容器。

cache_dir

-- 這是容器存儲文件的目錄。

filename_prefix -- 緩沖文件的前綴,例如:"cache_"。

shm -- shm

容器把緩沖數據放入***享內存,基準測試顯示,目前的實現下,這個容器的速度要比文件容器慢。

shm_key --

***享內存使用的鍵值。

shm_perm -- 使用***享內存數據段的權限。

shm_size --

分配***享內存的大小。

sem_key -- 信號燈的鍵值。

sem_perm -- 信號燈的權限。

db --

PEAR 的數據庫抽象層。

dsn -- 數據庫連接的 DSN 。可以參考 PEAR 的 DB 文檔。

cache_table --

表的名字。

phplib -- phplib

容器使用數據庫抽象層存儲緩沖。

db_class

db_file

db_path

local_file

local_path

ext/dbx

-- PHP

的數據庫抽象層擴展,如果像把緩沖存入數據庫,可以采用這個容器。

module

host

db

username

password

cache_table

persistent

使用

PEAR Cache 所得到的性能提升取決於妳所選擇的緩沖容器,例如,把數據庫的結果再次存入數據庫緩沖中就顯得毫無意義。

PEAR Cache

的函數緩沖模塊能把任何函數或者方法的結果緩沖,不論是 PHP

的內置函數還是用戶自定義函數,他缺省采用文件容器,把緩沖數據放入到壹個叫做function_cache 的目錄。

Cache_Function

類的構造器可以有三個可選的參數:

$container :緩沖容器的名字。

$container_options

:緩沖容器的數組參數。

$expires:緩沖對象過期的時間(秒數)。

普通的函數調用采用 Cache_Function 類的

call() 方法時,就能觸發緩沖。調用 call()

很容易,的壹個參數是函數的名字,然後是函數的參數,第二個參數是要調用函數中的第壹個,依此類推,我們來看例子:

例1

緩沖函數和方法的調用

// 調用 PEAR Cache 的函數緩沖。

require_once

'Cache/Function.php';

// 定義壹些類和函數。

class foo {

function

bar($test) {

echo

"foo::bar($test)

";

}

}

class bar {

function

foobar($object) {

echo

'$'.$object.'->foobar('.$object.')

';

}

}

$bar =

new bar;

function foobar() {

echo 'foobar()';

}

//

取得 Cache_Function 對象

$cache = new Cache_Function();

// 對 foo

類的靜態函數 bar() 作緩沖(foo::bar())。

$cache->call('foo::bar',

'test');

// $bar->foobar()

$cache->call('bar->foobar',

'bar');

$cache->call('foobar');

>

下面我們采用

Cache_Output 來把輸出作緩沖:

例2 緩沖腳本的輸出

// 加載 PEAR

Cache 的輸出緩沖

require_once 'Cache/Output.php';

$cache = new

Cache_Output('file', array('cache_dir' => '.') );

//

計算要緩沖頁面的標記,我們假定頁面的緩沖取決於

// URL, HTTP GET 和 POST 變量以及

cookies。

$cache_id = $cache->generateID(

array('url' =>

$REQUEST_URI, '

post' => $HTTP_POST_VARS, 'cookies' =>

$HTTP_COOKIE_VARS) );

// 查詢緩沖

if ($content =

$cache->start($cache_id)) {

// 緩沖命中

echo

$content;

die();

}

// 緩沖丟失

// -- 在這裏插入內容產生代碼

--

// 把頁面存入緩沖

echo $cache->end();

>

利用 Cache_Output 類,很容易把壹個動態的數據庫驅動的網站應用轉化為靜態,從而極大的提升站點的性能。越來越多的站點在采用 GZIP 壓縮

HTML 內容,這樣減少了服務器的帶寬消耗,對於使用 Modem 上網的用戶來說也能受益不少。

Cache_OutputCompression

擴展了 Cache_Output 類的功能,他把 GZIP 壓縮的 HTML 內容進行緩沖,從而節省了 CPU 壓縮的時間。

閱讀提示:在本篇文章中,我們將對PHP應用程序的分析、如何改變腳本代碼以及比較優化前後的各種參數值進行簡要的介紹。

PHP應用程序的性能優化

使用PHP編程的最大好處是學習這種編程語言非常容易以及其豐富的庫。即使對需要使用的函數不是十分了解,我們也能夠猜測出如何完成壹個特定的任務。

盡管PHP非常簡單易學,但我們仍然需要花費壹點時間來學習PHP的壹些編程技巧,尤其是與性能和內存占用相關的技巧。在PHP中,有許多小技巧能夠使我們減少內存的占用,並提高應用程序的性能。在本篇文章中,我們將對PHP應用程序的分析、如何改變腳本代碼以及比較優化前後的各種參數值進行簡要的介紹。

通過在程序中設置計時的程序,並反復執行這些代碼,我們可以獲得有關程序執行速度的壹組數據,這些數據可以可以用來發現程序中的瓶頸,以及如何進行優化,提高應用程序的性能。

也許讀者曾經聽說過PEAR庫吧。我們將使用PEAR庫創建在分析時需要使用的例子,這也是對現有的代碼進行分析的最簡單的方法,它使我們無需使用商用產品就能對代碼進行分析。

我們要使用的庫的名字是PEAR::Benchmark,它對於對代碼進行分析和性能測試非常有用。這個庫提供壹個名字為Benchmark_Timer()的類,能夠記錄壹個函數調用和下壹個函數調用之間的時間。在對代碼的性能進行測試時,我們可以得到壹個詳細的腳本執行結果,它非常簡單,如下所示:

include_once("Benchmark/Timer.php");

$bench

= new Benchmark_Timer;

$bench-> start();

$bench->

setMarker('Start of the script');

//

現在處於睡眠狀態幾分鐘

sleep(5);

$bench-> stop();

//

從計時器中獲得分析信息

print_r($bench->

getProfiling());

>

上面代碼執行後的輸出如下所示:

Array

(

[0] => Array

(

[name] =>

Start

[time] => 1013214253.05751200

[diff] =>

-

[total] => 0

)

[1] =>

Array

(

[name] => Start of the script

[time] =>

1013214253.05761100

[diff] => 9.8943710327148E-05

[total]

=> 9.8943710327148E-05

)

[2] =>

Array

(

[name] => Stop

[time] =>

1013214258.04920700

[diff] => 4.9915959835052

[total] =>

4.9916949272156

)

)

上面的數字似乎是壹組雜亂無章的數字,但如果程序的規模更大,這些數字就十分地有用了。

也許廣大讀者也能猜測到,數組的第壹個表目是實際調用Benchmark_Timer()類的方法,例如

$bench->

start()、$bench-> setMarker()和$bench->

stop(),與這些表目有關的數字是相當簡單的,現在我們來仔細地研究這些數字:

[0] => Array

(

[name] => Start

[time] => 1013214253.05751200

[diff] => -

[total] => 0

)

time表目指的是何時對Benchmark_Timer()的start()方法調用的UNIX的timestamp,diff表目表示這次調用和上次調用之間的時間間隔,由於這裏沒有上壹次,因此顯示出了壹個破折號,total表目指的是自測試開始到這壹特定的調用之前代碼運行的總的時間。下面我們來看看下壹個數組的輸出:

[1]

=> Array

(

[name] => Start of the script

[time] => 1013214253.05761100

[diff] =>

9.8943710327148E-05

[total] => 9.8943710327148E-05

)

從上面的數字我們可以看出,在調用$bench->

start()之後,程序運行了9.8943710327148E-05秒(也就是0.0000989秒)後開始調用$bench->

setMarker(....)。

壹次真實的性能測試經歷

盡管上面的例子不錯,但在對於決定如何優化妳的站點代碼設計方面,它真的不能算是壹個好例子。下面我將用我自己作為網站技術人員的壹段親身經歷來說明如何解決性能方面存在的問題。

我並不大理解網站使用的代碼,因為它是根據特殊的需求,歷經多年開發而成的━━其中的壹個模塊包括網站轉換代碼,另壹個模塊記錄網站的使用情況,其他的模塊也各有各的作用。我和網站的主要開發者都意識到網站的代碼需要優化,但又不清楚問題出在哪兒。

為了盡快地完成任務,我開始研究網站的主要腳本代碼,並在全部腳本代碼以及其包含文件中添加了壹些$bench->

setMarker()命令,然後分析$bench->

getProfiling()的輸出,並對得到的結果大吃壹驚,原來問題出在壹個與獲得特定語言名字(例如en代表english)的轉換代碼的函數調用中,該函數在每個頁面上都會被使用數百次。每次調用該函數時,腳本代碼都會對壹個MySQL數據庫進行查詢,從壹個數據庫表中獲得真正的語言名字。

於是我們這壹類的信息創建了壹個緩沖系統。經過短短2天時間的工作,我們使系統的性能得到了很大的提高,第壹周內頁面的瀏覽量也因此而增加了40%。當然了,這只是壹個有關分析代碼能夠提高互聯網應用或互聯網網站性能的例子。

性能測試函數調用

在分析壹個腳本或網頁(以及其包含文件)時,盡管Benchmark_Timer()特別有用,但它並不科學,因為要獲得分析的數據我們必須多次加載腳本,而且它也不是針對某個類或函數調用的。

PEAR::Benchmark庫中的另壹個被稱作Benchmark_Iterator的類能夠很好地解決這壹個問題,它能夠針對特定的函數或類的方法,顯示其分析信息。它的用途是能夠能夠從測試中獲得壹致的結果,因為我們知道,如果運行壹段腳本壹次,其運行時間為10秒,並不意味著它每次的運行時間總是10秒。

In

any case, let's see some examples:

//

連接數據庫的代碼

include_once("DB.php");

$dsn = array(

'phptype'

=> 'mysql',

'hostspec' => 'localhost',

'database'

=> 'database_name',

'username' =>

'user_name',

'password' => 'password'

);

$dbh =

DB::connect($dsn);

function getCreatedDate($id)

{

global

$dbh;

> $stmt = "SELECT created_date FROM users WHERE

id=$id";

// 在這裏使用PEAR::DB

$created_date = $dbh->

getOne($stmt);

if ((PEAR::isError($created_date)) ||

(empty($created_date))) {

return false;

} else

{

return $created_date;

}

}

include_once

'Benchmark/Iterate.php';

$bench = new Benchmark_Iterate;

//

運行getDate函數10次

$bench-> run(10, 'getCreatedDate', 1);

//

打印分析信息

print_r($bench-> get());

> 運行上面的代碼能夠產生與下面相似的結果:

Array

(

[1] => 0.055413007736206

[2] =>

0.0012860298156738

[3] => 0.0010279417037964

[4] =>

0.00093603134155273

[5] => 0.00094103813171387

[6] =>

0.00092899799346924

[7] => 0.0010659694671631

[8] =>

0.00096404552459717

[9] => 0.0010690689086914

[10] =>

0.00093603134155273

[mean] => 0.0064568161964417

[iterations]

=> 10

)

上面的這些數字很好理解,mean條目表示getCreatedDate()函數10次運行的平均時間。在進行實際測試時,應該至少運行1000次,但這個例子得出的結果已經足夠說明問題了。

  • 上一篇:215發卡網絡作弊?
  • 下一篇:如何在樹莓派上從源代碼構建Golang
  • copyright 2024編程學習大全網