http://www.laruence.com/2011/02/13/1870.html
你也許注意到過, 在PHP中使用ECHO輸出大段字串的時候, 執行時間會明顯的長, 也就會有朋友認為PHP的ECHO效能很差.
我在之前的文章中, 已經解釋過了原因, 也希望能糾正”PHP的ECHO效能差”的這個誤會.
然而之前的文章, 也僅僅是給出了原因, 並沒有介紹如何避免這個問題, 在今天公司內的某個產品線(Apache with PHP)發現了一個問題, 有使用者在短時間內大量發起下載請求, 導致http串連數和資料庫連接數劇增,
而資料庫連接數劇增的原因是因為資料庫的串連是單列模式, 一直到請求處理結束, 才會釋放資料庫連結. 這樣就有了一個問題, 如果請求處理時間過長, 就會造成大量的資料庫連結存在.
而這個使用者的網速很慢, 這也就意味著, ECHO的”效能”很差~, 下載時間很長~. 如所示:
ECHO執行
這也就引出了今天我要談的這個問題, 如何讓ECHO變快, 讓PHP的請求處理過程, 儘快結束…
我們知道, 之所以ECHO慢, 是在等待”寫資料”成功返回, 那麼一個比較簡單的辦法, 就是開啟輸出緩衝,
編輯php.ini
output_buffering = 4096 //byte當然, 你也可以在指令碼中, 顯示的調用ob_start():
ob_start();echo $huge_string;//其他的邏輯.ob_end_flush();這裡, 有一個要注意的地方, ob_start將會開闢一塊4096大小的buffer, 所以, 如果huge_string大於4096, 將不會起到加速的作用.
現在, 我們的ECHO就會”立即”執行成功, 返回. 因為資料暫時寫到了我們的輸出緩衝當中. 如果buffer足夠大, 那麼內容會等到指令碼的最後, 才一次性發送給用戶端(嚴格來說, 是發送給WebServer).
但這樣並不能解決我們今天遇到的這個問題, 因為這些資料到最後, 還是需要PHP去把它們發送給用戶端(此時不考慮WebServer的Output buffer), 這個過程不結束, 請求不會關閉, PHP也不會執行DB的解構函式~
那麼, 既然做夢, 那就再做大點, 我們可以使用Apache的輸出緩衝. 也就是改變成如下的執行流程:
加速ECHO
假設, 我們的PHP要輸出100K的資料, 那麼, 我們Apache的的輸出緩衝就必須大於100K, 否則當Apache的輸出緩衝滿了以後, 就會真正的發送給用戶端, 而這個過程中, 當時執行的ECHO就會阻塞等待.
那麼, 如何修改Apache的輸出緩衝呢? 我們可以在apache的設定檔中, 使用SendBufferSize配置指令:
SendBufferSize 4096 //注意是byt具體的SendBufferSize的說明, 參看http://httpd.apache.org/docs/2.0/en/mod/mpm_common.html#sendbuffersize
注: 其他的Webserver with php-cgi的模式, 請翻閱相關Webserver的手冊, 尋找類似配置.
現在, PHP的ECHO, 將直接把內容交給Apache, PHP在執行完成後, 不再等待內容發送給用戶端完成, 而直接退出. 而內容會在PHP處理完成以後, 由Apache發送給用戶端. 從而加速了ECHO的執行效率.
廢話一句: printf, print, file_put_contents(“php://output”)…等等, 和ECHO都是一樣的.
最後要說明, 這樣做, 只是把原來ECHO的等待時間, 轉移給了Apache, 並沒有真正的減少用戶端擷取到內容的時間. 它只是加速了PHP的處理過程, 提前了PHP的退出時機, 從而能減少PHP對資源的佔用時間, 間接增加資源的佔用率.