2010年2月21日

40 多個最佳化 PHP 的技巧

文章翻譯自下面網址:

http://reinholdweber.com/?p=3

1. 如果一個方法可以是靜態的,就將它宣告為靜態,這樣子會提昇四倍的效率

2. echo 會比 print 快

3. 使用 echo 的多參數模式,取代使用字串連結運算子
例如: echo $arr1,$arr2,$arr3; 會比 echo $arr1 . $arr2 . $arr3; 來的快

4. 在 for 迴圈執行之前設定最大次數,而不是在迴圈執行過程中決定
例如:

for($i = 0; $i < 10; $i ++) {
echo ‘test’, chr(10);
}

比這樣好:

for($i = 0; ; $i ++) {
echo ‘test’, chr(10);
if($i == 10) break;
}

5. 移除變數(unset())來釋放記憶體,特別是大型陣列

6. 避免使用神奇方法,像是 __get, __set, __autoload

7. 避免使用 require_once()
也就是說,盡可能確認一個執行程序中,對於單一檔案只進行一次的引用

8. 透過 include 與 require 引用檔案時盡可能使用絕對(完整)路徑,減少處理作業系統路徑的時間

9. 如果想要知道程式開始執行的時間(例如在進行效能評估時), $_SERVER[’REQUEST_TIME’] 會比 time()正確

10. 盡可能試著用 strncasecmp()、 strpbrk() 與 stripos() 等函數取代樣式比對

11. str_replace 會比 preg_replace 來的快,而 strtr 比 str_replace 更快四倍

12. 如果有函式(例如字串替換函數)同時接受陣列與字串作為參數,而要使用的參數也不會太多,可以嘗試多寫幾行程式,每次處理一個字串,取代在一行程式中傳送陣列作為參數的形式

13. 使用 switch() 語法會比大量 if, else if 好

14. 透過錯誤抑制運算子 @ 會拖慢程式速度

15. 啟用 apache 的 mod_deflate

16. 在結束資料庫操作後將連線關閉

17. $row[’id’] 會比 $row[id] 快七倍
也就是說,清楚定義陣列的索引會比較好

18. 盡可能不要放任錯誤訊息存在
也就是說,不要刻意關掉系統對於錯誤訊息的提示來忽略錯誤訊息

19. 在 for 迴圈中,不要在開始的地方使用函數,例如 for ($x=0; $x <>

20. 在方法中使用局部變數比較快,跟在函數中使用一樣意思
也就是說,能夠用局部變數進行的工作,就不需要刻意產生一個物件屬性(var $foo;)、全域變數(global $foo;)

21. 增加一個全域變數會比局部變數慢兩倍

22. 增加一個物件屬性(例如: $this->prop++)會比局部變數慢三倍

23. 增加一個未事先定義的局部變數會比預先定義的形式慢 9~10 倍

24. 在函式中宣告一個用不到的全域變數會讓速度變慢(相對於增加同樣數量的局部變數),PHP 也許是增加了檢查全域變數存在與否的時間

25. 方法的執行效能似乎是獨立於物件中定義的數量,在測試物件中增加 10 個方法(在要測試的方法之前與之後)對於效能沒有任何影響

26. 在衍生的物件中執行的方法會比繼承而來的方法快

27. 執行帶有一個參數且沒有內容的函式,時間大約等於 7~8 次的 $localvar++ ,而透過物件方法進行類似的測試則約等於 15 次的 $localvar++ 時間。

28. 透過單引號使用字串會比雙引號快一些,因為 PHP 會在雙引號的字串中嘗試找尋有無變數

29. 似乎跟 3. 重複

30. 在 Apache 中,一個 PHP 程式比靜態的 HTML 頁面慢 2 ~ 10 倍,可以試著使用更多的靜態 HTML 取代 PHP 程式

31. PHP 程式會在每次執行時再次編譯,除非使用快取;安裝一個 PHP 快取程式基本上可以增加 25% ~ 100% 的效能,因為省去了編譯的時間

32. 盡可能使用快取,像是 memcached。memcached 是一個高效能的記憶體物件快取系統,透過減少資料庫存取來提昇動態網站應用程式,快取中間碼(OP code)讓程式不需要每次執行都進行編譯。

33. 需要檢查字串是否為指定長度時一般都會透過 strlen() ,這個函式很快,因為它不會執行運算,只是將 zval 結構(PHP 用來儲存變數的內部 C 語言結構)中已知長度傳回。不過因為 strlen() 是一個函式,執行函式的操作會有些程序,像是轉小寫與搜尋雜湊表,如果能夠,透過 isset() 會快上許多。
例如:
if (strlen($foo) < 5) { echo “Foo is too short”; }
相對於
if (!isset($foo{5})) { echo “Foo is too short”; }

執行 isset() 會比 strlen() 快一些,因為 isset() 是一個語言結構,而非函式,所以不需要進行轉小寫或搜尋雜湊表的程序,意味著檢驗字串的長度實際上不會造成額外的負擔

34. 增加或減少一個變數的數值時, $i++ 比 ++$i 慢一些,這個情況只有在 PHP 才會發生,因為 $i++ 使用了四個中間碼, ++$i 只要三個,後置增加語法實際上會產生一個暫存變數,而前置形式則是直接增加原本變數,這是一個用在 Zend’s PHP optimizer 的中間碼最佳化技巧。記住這個方法,因為並非所有最佳化引擎都會執行這個動作,而更有許多主機連最佳化程式都沒有安裝。

35. 並非所有東西都得物件導向,呼叫方法與物件需要大量的記憶體

36. 不要將所有資料結構都定義為物件,陣列也是很有用的

37. 不需要把方法切的太細,想清楚,哪些是真正會重複使用的

38. 在需要的時候,可以隨時進行方法的切割

39. 盡可能使用預先定義的函式(PHP預設的)

40. 如果有非常耗時間的函式,不妨將它寫成 C 語言的外掛

41. 探查程式碼的輪廓,一個輪廓探查工具可以顯示個別程式碼執行所需要的時間,而 Xdebug 除錯工具已經包含了這樣的功能,探查輪廓可以檢視整體效能瓶頸

42. Apache 的模組 mod_gzip 可以壓縮需要傳輸的資料,最多達 80%

43. John Lim 提供了另一篇 PHP 最佳化的文章:

http://phplens.com/lens/php-book/optimizing-debugging-php.php