幾個增加 PHP 網站效能的方法

我個人從事網站程式設計工作很久 , 尤其對 PHP 很喜愛 ,  也玩了不少的架構 , 以下就是提出一些自己的經驗與大家分享 , 要如何讓 PHP 的網站跑的更快更穩

1. 安裝 OP Code Cache 軟體

因 PHP 本身屬於直譯式語言 , 每支 PHP Script 在執行前會先被翻譯成 OP Code , 然後再去執行 OP Code , 因此市面上就有針對 OP Code 進行快取的軟體 , 這類的軟體運作方式都是以 PHP extenstion 方式外褂 , 目前市面上免費的推薦 APC 與 XCache , 網址分別如下 :

APC : http://pecl.php.net/package/APC
XCache : http://xcache.lighttpd.net/

當然還有其他如 EAccelerator 很有名 , 但這套很久沒更新了就不推薦了 , 其中 XCache 是由華人 Moo 開發的 , 我這網站的機器也是安裝 XCache , 而 APC 在 PHP 6.0 會內建 , 當安裝這類軟體之後 , 會非常明顯感受到 PHP 網頁"開啟"速度加快 , 這是因為這類軟體在快取了 OP Code 之後就不會再去直譯 PHP Script 了 , 所以我會說是 "開啟" 速度加快 , 而非真正的執行速度加快 , 但對於網頁來說 , 網頁本身的執行時間都很短 , 大部分也都是耗在 PHP 直譯的時間 , 所以安裝這種軟體可以用肉眼就可感覺到加速效果
 

2. 安裝 Zend Optimizer

這套軟體是免費的 , 它會針對 OP Code 作最佳化 , 但是實際上我們也無法用肉眼感覺到加速效果 , 這個 Zend Optimizer 我個人主觀認為是 Zend 為了商業利益而推出的 , 一方面是宣導其具備加速效果 , 所以大家可能會安裝 , 另一方面它有推出 PHP Encoder 可對 PHP 作加密的編碼 , 而要解碼就一定要用 Zend Optimizer 了 , 有點像在先鋪好解碼的平台
 

3. Web Server 的選擇

大家最常看見的 PHP 執行平台要嘛是 Apache , 要嘛是 IIS , 事實上還有一套叫做 lighttpd 的 Web Server , 這套 Web Server 真的很快 , 而且吃很少記憶體 , 因為他在預設的模式下只有一個行程(Process) 在執行 , 它是以 Fast CGI 協定與 PHP 溝通 , 所以記憶體用量就完全是看 PHP 被執行的數量了 , 當然 lighttpd 也有它不足之處 , 例如不像 Apache 可支援 htaccess , 但對於大流量的大型網站 , lighttpd 真的是首選 , 例如 YouTube 就是用 lighttpd , 而且他是免費的 . 但是在 Windows 平台上則不支援 , 有點可惜就是了 ..

目前市面上最多人用的仍是 Apache + PHP 這種架構 , 這種方式我本以為在 Apache 2.0 加入了多執行緒(Multi Thread)後可以改善網站效能 , 但實際上 Apache僅能以 prefork 方式才能正常的和 PHP 一起跑 , PHP 的官方也宣稱建議用 prefork 模式跑 , 這代表著 Apache 2.0 甚至 2.2 的版本和 PHP 一起跑的方式與 Apache 1.3 沒有兩樣 , 在高流量的網站效能測試上仍然是表現的很差 , 而且 fork 行程真的超吃記憶體 , 當然 Apache 也可以使用 FastCGI 協定改以多執行緒模式和 PHP 一起運作 , 不過這樣在執行 PHP 時又不能搭配 htaccess 的功能了 , 所以若有多個用戶要共用一台機器 , 當然還是要使用 prefork + mod_php 的方式來執行才有 htaccess 功能 , 但若是單一用戶的大流量網站 , 我非常推薦使用 lighttpd ( http://www.lighttpd.net )

4. 能盡量把資料庫內容快取就快取

應該很多人寫 PHP 會搭配一些 DB Layer , 例如 ADODB , 我個人最近則是偏好使用 Zend Framework , 所以 DB Layer 自然就是使用 Zend_DB 了 , 用 DB Layer 的優點就是讓程式更美更好維護 , 但效能上絕對比用原生的 database function 來的差 , 因此就必須靠一些取巧的方式 , 像 ADODB 就可以把資料作快取 , 很多的 DB Layer 都有此功能 , 能盡量少去執行 SQL 自然就可以讓程式快點跑完 , 網站當然就變快了

5. 打開 Web Server 的輸出壓縮功能或 PHP 的輸出壓縮功能

大部分的 Web Server 有支援網站內容輸出的壓縮 , 不過應該都要自個兒去設定開啟 , 像 Apache 只要打開此功能 , 不論靜態網頁或 PHP 的輸出都可以得到壓縮 , 壓縮過後自然就會佔用較少的頻寬 , 以 End User 觀點來看 , 會明顯感受到網頁比較快打開了 , 這並不是網站效能增強了 , 而是內容所佔用的頻寬變少自然就比較快下載完了 , 但有時候我們的網站是租用虛擬主機沒辦法打開此功能時 , 就僅能依靠 PHP 本身提供的 ob_start() 函數來做內容輸出壓縮了 , 這種方式僅對 PHP 本身有壓縮效果 , 對於 css , js 檔案就沒辦法壓縮了

使用此方法會稍微耗用 CPU 的資源 , 這需要取得平衡點 , 如果網站本身提供的頻寬就不大 , 用這方法確實可以節省頻寬 , 但若同時間 Request 的數量太多 , 有可能會讓 CPU 使用率飆高 , 但通常我們會希望來站上的人越多越好吧 ... 真的太多人 , 就增加 Web Server 吧 , 用 Loading Balance 的架構來服務 , 不過這又牽扯到另一方面的專業 , 總之打開輸出壓縮是不錯的選擇啦

6. 別被 Template Engine 號稱的 MVC 給誤導了

PHP 本身就是個很棒的 Template Engine , 很多 PHP 程式設計師包括我以前在內 , 都超愛 Smarty 這個 Template Engine , 這種 Template Engine 確實可以把 View 部分獨立出來 , 但若只這樣作絕對不是 MVC , 若只單純把 View 部分獨立出來對程式設計師有什麼好處 ??? 先問問自己的良心 , 除了效能降低外 , 真的能夠讓美工人員可以和程式人員分開作業又好整合嘛 ????

我相信所有的美工人員最愛的還是 Dreamweaver 吧 , Dreamweaver 本身就可以認得 PHP Tag , 而且會特別標示一個 "PHP Icon" , 我相信美工人員看到 PHP Icon 尚不會破壞所見即得的編輯版面會較容易接受 , 但是用了 Smarty 之後 , 美工人員不見得會愛 , 因為版面變成一堆更怪的 tag 出現了 , 而且 Dreamweaver 不認得 (不過有外褂) , 但照我多年的經驗 , 到最後版面的處理仍是會回到程式人員手上 , 信不信 ?

既然如此 , 花了那麼多精神去玩 Template Engine 幹麼 ? 要讓程式和 HTML 變得更好看 , Zend Framework 的 Zend_View 是不錯的作法 , 他仍是把 View 分開 , 但 View 部分預設仍是以 PHP 來撰寫 ,  不會有怪怪的標籤出現在 Dreamweaver 了 , 而且效能還不賴 , 當然若是較小型的網站 , 甚至 PHP 和 HTML 寫在一起的傳統作法仍是可行 , 只是寫的方法改一下 , 就可以把 PHP 和 HTML Code 分的比較清楚了 .... 怎麼做 ??? 很簡單 , 所有的邏輯運算全都寫在最前面就好了 , HTML 就放在 PHP 後面就好囉

<?php
  // 邏輯運算 , 資料庫操作 , 等等都寫這
?>
<body>
<table>
<?php foreach( $rows as $row ) :?>
<tr><td><?php echo $row['col1']; ?></td><td><?php echo $row['col2']; ?></td></tr>
<?php endforeacn;?>
</table>
</body>
這樣是不是仍可以把 PHP 和 HTML 分的清楚呢 , 甚至 HTML 的部份也可以另外存檔在其他目錄 , 在我們的主程式中用 include 就可以加進來 , 是不是也是另一種把 View 獨立成某個檔的最快作法呢 ?
當然 , 若你所開發的產品是屬於可讓 End User 編輯版面那類的 , 例如無名的 Blog , 你可能就真的需要用到 Smarty 這類的 Template Engine 了 , 畢竟你可能不想讓 End User 能夠寫 PHP 程式碼吧 , 但若自己開發的產品並無此需求 , 僅僅只是要好維護 , View 能獨立開來 , 我勸大家遠離 Smarty 吧 ...

 待續 ... 想到會再寫 , 可能會以此篇再分支出各種加速法的詳細介紹吧 ...

6 則評論在 幾個增加 PHP 網站效能的方法.

  1. 我覺的你對Smarty真是一知半解,我很不認同你對smarty的說法,誰說smarty的版型
    對DW就會是一堆其怪的TAG呀,你是不知道有left_delimiter跟right_delimiter這二
    個方法來改變TAG嗎,還有誰說美工人員就不會去改到程式的部份,有時候檔案太多
    美工人員也會眼花的好嗎,Smarty只有在第一次存取的時候會比較慢一點,但當他生
    成Template檔之後,就跟一般php檔沒二樣了呀,還有就是把view分開,這本來就是
    程式界一貫的做風呀,一來程式碼乾淨比較容易維護,二來檔案也不至於過大,三來
    整個看起來就是舒服啦,.Net ASP也是這樣呀,ASPX檔是版面檔,然後不管是.cs或
    .vb都是程式檔,這樣程式與版面分離不來就是王道的東西,怎被你講的一文不值,
    真的是聽你在胡扯…..

  2. @路人甲
    報告路人甲
    Smarty 1.0 出來的時候就在玩了 , 當時確實有為了版型這方面苦惱 , 因此那時候用 Smarty 久了很順手
    隨著 MVC 作法出來 , 以及後來想通之後才有此感覺得
    Smarty 本身的物件就已經在初始化時比較慢了 , 此為效能的缺陷之一
    且 Smarty Compilie 之後的 code 與自己用 PHP 寫得比較起來多了太多不必要程式導致效能降低
    Smarty 的 tag 可以改變沒錯 , 常見到很多人用 <!–{ } –> 的做法, 但怎麼改成 Dreamweaver 可以去特別標示在所見即得的編輯畫面呢 ? 頂多會變成註解 icon , 至於預設標籤除了安裝 Dreamweaver plugin 外別無他法了 , 美工人員到底知不知道這是註解還是程式碼 ?
    當初用 Smarty , 會受到一種誤導 , 就是可以把網頁設計與程式邏輯分開
    事實上不然 , Smarty 也有 Smarty 的邏輯
    且網頁設計師或美工不黯程式邏輯 , 最終依然得依靠程式人員修改版型 , 甚至在分工上 , 美工設計玩網頁後
    接下來的 Template 製作是給程式做完之後 , 爾後也不會交還給美工了 , 因為 Template 中已經包含 Smarty Code 再回頭給美工弄肯定出事情
    既然如此 , PHP 本身就是個很好的 Template , 用 PHP 作 View 和 Smarty 作 View 都是程式人員在作 , 又何必多加一層負擔的捨近求遠呢 ?
    也因此 , 第一個用 PHP 作為 Template http://phpsavant.com/ 這套其實當初就有發現他了
    只是當時沒想通 , 後來這套的作者也有參加 Zend Framework 中的 Zend_VIEW 開發

    以 .NET 而言 , 至少在版面的修改上有良好的編輯器可以選擇 , 但 smarty 卻沒有 , 差別是在這 , 就算現在有了 , 我想沒有人會放心給美工改 Template , 一定還是程式人員幹這種事情
    我現在是比較推崇目前的 MVC Framework 作法啦 , 因為以 php 作為 view 確實開發起來簡潔又快速
    ASP.NET MVC 也是這樣不是嗎 ?
    如果你很喜歡 ASP.NET 原始作法 , 反而 Prado 這套Framework比較像 , 但效能非常差 , 畢竟Language特性和.NET不同以致如此
    原始的 ASP.NET 也不會有怪怪的 smarty literal 的對吧 , 這看起來很礙眼

    此篇文章也僅是就效能而論而已 , 因為我知道很多人愛用 Smarty , 想當初至少超過兩年的時間我也一直用 Smarty 開發專案
    因此深知 Smarty 效能之差 , 其實多的是比 Smarty 效能高上幾倍的 Template Engine 哩 , 但 Smarty 畢竟是 PHP 社群中在主推的 , 所以很多人用 , 就大家說好 , 而且現實情況下 , 我當時會用 Smarty 也是因為大家都會 , 於是就大家一起用免得要再學
    但隨著作的案子越來越朝流量大且功能複雜的網站 , Smarty 的缺點就顯露無疑

    現今的 MVC Framework , 似乎 CakePHP 很多人台灣人在推廣叫好(我很那悶) , Zend Framework 是官方主推
    我寫這篇文時 , 是 2008 年 , 以現今的觀點來看 , CakePHP , Zend Framework 也是犯了效能的致命傷 , 後期則出現效能更快的 如 CI , YII , DooPHP , 我現在都用 YII 開發 , 也很期待 Symfony2

    看看別人怎麼看 Smarty 效能吧
    http://www.kuwata-lab.com/support/2007/11/03/why-smarty-is-too-slow/

  3. @路人甲:
    說真的。其實我沒有走過smarty這一段路。
    打從我從去年學php→到排斥函式→到接受函式→到排斥物件→到接受物件。
    打從了解現在的老闆一直在給我的知識和觀念之後。
    也想都沒想的就直接被老闆塞了codeigniter給我。
    不過他在塞給我的同時送我了一句話:知識!取決於所知的範籌。
    或許因為沒經歷過smarty那一段路,所以把php當成template engine這種事對我而言就會是理所當然的。
    也看了很多關於smarty和php template engine之間的爭執。
    以偏心來說,我的心當然是向著php template engine來做。
    其實,越是簡單的東西,他越不簡單,而往往被認為高度複雜的東西,有可能就只是簡單的集合體而已。
    其實之前pigo大在php論壇提及面試的人不懂pdo,說真的,我要去面試我也不懂。(還是看過之後才去思考pdo的用途)
    不過,也不是表示說,沒有pdo,我就沒注意到安全性的問題。
    反過來是說,其實我是自己寫了過濾資料的物件。
    很多東西都有設計者他當初的用心和想法 -> 即便這些想法有時候會被打破。
    即便有些事候……有些東西不被人們所知道。(這又是一個問題,市售的php只教入門不教進階。不玩物件
    的人自然也不會去考慮pdo是什麼,反個說,也沒人會去管怎麼寫一個可以主動載資料及過濾資料的物件)
    人的無知不是最可怕的,可怕的是無知之餘又不肯學習。
    大多數很多人跟我爭執一些問題所在,其實我比較關心的不是說他和我的意見上的衝突。
    而是在於,對了!能不能繼續精進。錯了,願不願意修正並且再精進。
    但不管如何,別人對某件事情是否真的是一知半解這不能從言語中看得出來。
    萬一人家只是裝傻笑笑,那認真的話反而被人當成傻瓜。
    更多的時候,或許人家已然經歷過某些歷程,只是不為人知。
    每個人都有自己的一套心得理論。
    聰明的人,是見到別人的優點學起來。
    不是看到別人的缺點(其實往往不會是缺點,大多的來由可能來自於自己的妒嫉心理),就無理謾罵。
    額外提及,也感謝PIGO大是第一個讓我知道PDO這個東西的人。
    雖然其實至今我仍然沒在用就是了。(因為CI本身有DB,他已經有他過濾的方式之外,其實我自己還是加了
    我之自己過濾用的lib)
    不過可以從PDO的方面來強化自己所做出來的功能性物件這事上,倒是給了我不少的靈感。

  4. @tkdmaf
    嘿嘿
    別亂扣帽子呀
    我從來沒有對不會 PDO 的人說些甚麼話
    那是另一個人(Sxxxx)說的
    我只是在面試時會問 sql injection 問題 呵呵 , 會 mysql function , 就該知道如何用 mysql function 處理 sql injection , 會pdo 就要知道 pdo 如何去防
    我從來沒有要求一定要會 pdo 喔 呵呵

發佈留言