近來做了一陣子程式效能的最佳化工作,有個比較有趣的想法,想提出來跟大家交流一下。
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 .= ";);rn";
}
$data_cache = "?>rn";
// 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圖形。一般地,對於所有其他文件,這種壓縮都有效,但建議你針對各種瀏覽器都分別進行測試,特別是當你使用了特殊的插件或資料檢視器時這一點尤其重要。