我們在編寫程序時,總是想要使自己的程序占用資源最小,運行速度更快,代碼量更少。往往我們在追求這些的同時卻失去了很多東西。下面我想講講我對PHP優化的理解。優化的目的是花最少的代價換來最快的運行速度與最容易維護的代碼。
進行大范圍的優化,而不是死啃某些程序代碼
我這裡所說的優化,基本上都是從服務器,Apache,數據庫這些方面來進行的優化,而並不是對你的PHP代碼加以改進從而提高程序的運行速度,因為比起你將程序中的正則優化為字符串處理函數從而提升程序速度來說,在大范圍內進行的優化所需要的代價要比這個小的多,而獲得報酬卻要豐厚的多。
在非代碼處進行優化有以下好處:
1、通常情況下能夠大大提高效率
2、不會危及到代碼的完整性
3、能夠快速部署
緩存技術
下面來說說常用的緩存技術,通過這些緩存技術能夠大大的提高效率
在說到緩存技術的時候不得不提到memcached ,memcached是高效、快速的分布式內存對象緩存系統,主要用於加速 WEB 動態應用程序。
Memcached的原理
memcached 是以守護程序方式運行於一個或多個服務器中,等待接收客戶端的連接操作,客戶端可以由各種語言編寫(例如PHP)。PHP 等客戶端在與 memcached 服務建立連接之後,接下來的事情就是存取對象了,每個被存取的對象都有一個唯一的標識符 key,存取操作均通過這個 key 進行,保存到 memcached 中的對象實際上是放置內存中的,並不是保存在 cache 文件中的,這也是為什麼 memcached 能夠如此高效快速的原因。
說完memcached,下面來說說常用的緩存方法
1、編譯與OPCODE緩存
因為PHP是解釋型的語言,所以每個PHP文件在運行的時候都需要編譯後再執行,同一個文件,不同的用戶訪問,或者同一個用戶不同時間訪問同一個文件,每次都需要重新編譯然後運行,這樣就耗費了大量時間。
通過編譯緩存每個文件在修改之後只編譯一次這樣就減少了文件IO操作,用戶訪問後機器指令直接從內存中取出並執行而不是硬盤中讀出。
最常見的PHP編譯緩存工具有:APC,Accelerator,xcache
2、全局頁面緩存– Squid Cache
Squid Cache(簡稱為Squid)是一個流行的自由軟件(GNU通用公共許可證)的代理服務器和Web緩存服務器,Squid作為網頁服務器的前置cache服務器通過緩存相關請求來提高Web服務器的速度。
3、局部緩存之SQL緩存
在大多數應用程序中主要的瓶頸往往可以追溯到數據庫的操作中,一般都是因為復雜的數據庫查詢而耗費了大量時間,而SQL緩存可以大大降低復雜查詢造成的負荷。
SQL緩存的例子(使用了memcached擴展)
代碼片段:
$key = md5(“some sort of sql query”);
if (!($result = memcache_get($key))) {
$result = $pdo->query($qry)->fetchAll();
// 緩存查詢結果一小時
memcache_set($key, $result, NULL, 3600);
}
4、局部緩存之代碼塊緩存
為了優化PHP程序,有時候我們不得不優化一個個代碼段來減少那麼一點點的執行的時間,但是比起優化復雜的不同的PHP代碼段還不如通過緩存來直接忽略這些代碼段的優化,這樣做的好處是:
1、能夠很快的看到效果
2、不會破壞以前的代碼
3、速度要比優化代碼要快得多
代碼塊緩存的列子(同樣使用了memcached擴展)
代碼片段:
function complex_function_abc($a, $b, $c) {
$key = __FUNCTION__ . serialize
(func_get_args());
if (!($result = memcache_get($key))) {
$result = //函數代碼
// 儲存執行結果1小時
memcache_set($key, $result, NULL, 3600);
}
return $result;
}
當然除了上述方法外還可以用到文件緩存(將數據庫中的數據取出儲存在文件中),還可以生成靜態HTML文件等,但是這些方法的緩存還是將文件儲存在硬盤上而不是內存中。
輸出控制
除了上述緩存技術外還可以通過輸出控制來讓程序執行的時間更少
下面通過PHP與APACHE來說說輸出控制
1、PHP輸出控制
這裡最主要用到ob_start()以及PHP中的OB系列函數,這些函數可以做什麼呢?
第一就是靜態模版技術。所謂靜態模版技術就是通過某種方式,使得用戶在client端得到的是由PHP產生的html頁面。如果這個html頁面不會再被更新,那麼當另外的用戶再次浏覽此頁面時,程序將不會再調用PHP以及相關的數據庫,對於某些信息量比較大的網站,例如sina,163,sohu。類似這種的技術帶來的好處是非常巨大的。
代碼示例:
<?php
ob_start(); //打開緩沖區
?>
php頁面的全部輸出
<?php
$content = ob_get_contents(); //取得php頁面輸出的全部內容
$fp = fopen(“output.html”, “w”); //創建一個文件,並打開,准備寫入
fwrite($fp, $content); //把php頁面的內容全部寫入output.html,然後……
fclose($fp);
?>
當然這個ob系列函數還有其他很多用處我就不在這裡一一說明了。
2、apache輸出控制
將SendBufferSize設置為頁面大小,這樣就能將頁面一次性放在發送緩沖區從而增加處理速度。
SendBufferSize 指令
說明:TCP發送緩沖區大小(字節)
語法:SendBufferSize bytes
默認值:SendBufferSize 0
作用域:server config
狀態:MPM
模塊:beos, mpm_netware, mpm_winnt, mpmt_os2, prefork, worker
這個指令設置服務器的TCP發送緩沖區的大小(字節)。提高這個值會導致兩個後果:高速度和高潛伏時間(100ms左右)。如果設置為”0″,將使用操作系統默認值。
通過源代碼方式編譯你的Apache/PHP/Database 可讓你的程序增加10–15%的速度
下面再說說在代碼優化的時候應該注意的
1、短代碼不等於快的代碼
很多人在寫程序時希望將代碼寫的越簡潔越好,但是越短的代碼有時候反而需要更長的執行時間,所以哪怕是用更多的代碼也不使用速度慢的代碼
2、在寫程序的時候更應該注重程序的擴展性,而不是追求速度
3、在優化你的代碼之前,先看看跟數據庫有關的部分,因為大多數應用程序的瓶頸在數據庫而不是代碼
4、微優化得不償失
什麼叫做微優化?就像前面所說的將正則表達式部分的代碼改用字符串函數代替。這樣做有以下缺點:
(1)花費時間較長
(2)不會解決你的性能問題
(3)很有可能會破壞以前的代碼從而產生未知的錯誤
(4)付出大於回報
這裡還不得不提到一個誤區,有些人為了讓程序更加優化,在分析業務邏輯的時候便將優化考慮在內了,從而為了得到更優的代碼而改動業務邏輯。這是十分愚蠢的想法,因為程序的目的便是為了處理現實中遇到的問題,是為這些問題服務的,怎麼能本末倒置呢。