1 字符串
1.1 少用正則表達式
能用PHP內部字符串操作函數的情況下,儘量用他們,不要用正則表達式, 因爲其效率高於正則。
str_replace函數要比preg_replace快得多,strtr函數又比str_replace來得快。
1.2 字符替換
str_replace字符替換比正則替換preg_replace快,但strtr比str_replace又快1/4。
另外,不要做無謂的替換,即使沒有替換,str_replace也會爲其參數分配內存。
用 strpos 先查找(非常快),看是否需要替換,如果需要,再替換。
1.3 壓縮大的字符串
使用 gzcompress() 和 gzuncompress() 對容量大的字符串進行壓縮和解壓,再存入和取出數據庫。
這種內置的函數使用gzip算法,能壓縮字符串90%。
1.4 echo 輸出
echo 字符串用逗號代替點連接符更快些。
雖然,echo是一種語言結構,不是真正的函數。
但是,它可以把逗號隔開的多個字符串當作“函數”參數傳入,所以速度會更快。
echo $str1, $str2; // 速度快
echo $str1 . $str2; // 速度稍慢
1.5 儘量用單引號
PHP 引擎允許使用單引號和雙引號來封裝字符串變量,但是它們的速度是有很大的差別的!
使用雙引號的字符串會告訴 PHP 引擎,首先去讀取字符串內容,查找其中的變量,並改爲變量對應的值。
一般來說字符串是沒有變量的,使用雙引號會導致性能不佳。
最好使用字符串連接,而不是雙引號字符串。
1.6 使用isset代替strlen
在檢驗字符串長度時,我們第一想法會使用 strlen() 函數。
此函數執行起來相當快,因爲它不做任何計算,只返回在zval結構(C的內置數據結構,用於存儲PHP變量)中存儲的已知字符串長度。
但是,由於strlen()是函數,多多少少會有些慢,因爲函數調用會經過諸多步驟,如字母小寫化、哈希查找,會跟隨被調用的函數一起執行。
在某些情況下,你可以使用 isset() 技巧加速執行你的代碼。例如:
if (strlen($foo) < 5) {
echo "Foo is too short";
}
// 使用isset()
if (!isset($foo{5})) {
echo "Foo is too short";
}
1.7 用split分割字符串
在分割字符串時,split()要比explode()快。
1.8 echo效率高於print
因爲echo沒有返回值,print返回一個整型。
2 語句
2.1 最好不用@
用@掩蓋錯誤會降低腳本運行速度,並且在後臺有很多額外操作。
用@比起不用,效率差距 3 倍。特別不要在循環中使用@。
2.2 避免使用魔術方法
對於__開頭的函數就命名爲魔術函數,它們都在特定的條件下觸發。
這些魔術函數包括:__construct()、__get()、__call()、__autoload()等等。
以__autoload() 爲例,如果不能將類名與實際的磁盤文件對應起來,將不得不做大量的文件存在判斷。
而判斷文件存在需要磁盤I/O操作,衆所周知,磁盤I/O操作的效率很低,因此這纔是使得autoload機制效率降低的原因。
因此,在系統設計時,需要定義一套清晰的、將類名與實際磁盤文件映射的機制。
2.3 別在循環裏用函數
例如:
for($x=0; $x < count($array); $x++) {
}
這種寫法在每次循環的時候都會調用 count() 函數,效率大大降低,建議這樣:
$len = count($array);
for($x=0; $x < $len; $x++) {
}
2.4 使用三元運算符
在簡單的判斷語句中,三元運算符?:更簡潔高效。
2.5 使用選擇分支語句
switch、case好於使用多個if、else if語句,並且代碼更加容易閱讀和維護。
2.6 屏蔽敏感信息
使用 error_reporting() 函數來預防潛在的敏感信息顯示給用戶。
理想的錯誤報告應該被完全禁用在php.ini文件裏。
如果用的是共享虛擬主機,php.ini不能修改,最好添加 error_reporting() 函數。
放在每個腳本文件的第一行,或者用require_once()來加載,能有效的保護敏感的SQL查詢和路徑,在出錯時不被顯示。
2.7 不實用段標籤<?
不要使用開始標誌的縮寫形式,你正在使用這樣的符號嗎<?,應該用完整的<?php開始標籤。
當然,如果是輸出變量,用<?= $value ?>這種方式是鼓勵的,可以是代碼更加簡潔。
2.8 純PHP代碼不加結束標記
如果文件內容是純 PHP 代碼,最好在文件末尾刪除 PHP 結束標記?>。
這可以避免在 PHP 結束標記之後萬一意外加入了空格或者換行符,會導致 PHP 開始輸出這些空白,而腳本中此時並無輸出的意圖。
3 函數
3.1 儘量使用PHP內部函數
內置函數使用C語言實現,並且經過PHP官方優化,效率更高。
3.2 使用絕對路徑
在include和require中儘量使用絕對路徑。
如果包含相對路徑,PHP會在include_path裏面遍歷查找文件。
用絕對路徑就會避免此類問題,解析路徑所需的時間會更少。
3.3 包含文件
儘量不要用require_once和include_once包含文件,它們多一個判斷文件是否被引用的過程,能不用盡量不用。
而使用require、include方法代替。
3.4 函數快於類方法
調用只有一個參數、並且函數體爲空的函數,花費的時間等於7-8次$localvar++運算。
而同一功能的類方法大約爲15次$localvar++運算。
3.5 用子類方法
基類裏面只放能重用的方法,其他功能儘量放在子類中實現,子類裏方法的性能優於在基類中。
3.6 類的性能和其方法數量沒有關係
新添加10個或多個方法到測試的類後,性能沒什麼差異。
3.7 讀取文件內容
在可以用file_get_contents()替代file()、fopen()、feof()、fgets()等系列方法的情況下,儘量用file_get_contents()。
因爲他的效率高得多!
3.8 引用傳遞參數
通過參數地址引用的方式,實現函數多個返回值,這比按值傳遞效率高。
方法是在參數變量前加個 &。
4 變量
4.1 及時銷燬變量
數組、對象和GLOBAL變量在 PHP 中特別佔內存的,這個由於 PHP 的底層的zend引擎引起的。
4.2 使用$_SERVER變量
如果你需要得到腳本執行的時間,$_SERVER['REQUSET_TIME']優於time()。
4.3 方法裏建立局部變量
在類的方法裏建立局部變量速度最快,幾乎和在方法裏調用局部變量一樣快。
4.4 局部變量比全局變量快
由於局部變量是存在棧中的。
當一個函數佔用的棧空間不是很大的時候,這部分內存很有可能全部命中cache,CPU訪問的效率是很高的。
相反,如果一個函數同時使用全局變量和局部變量,當這兩段地址相差較大時,cpu cache需要來回切換,效率會下降。
4.5 局部變量而不是對象屬性
建立一個對象屬性(類裏面的變量,例如:$this->prop++)比局部變量要慢3倍。
4.6 提前聲明局部變量
建立一個未聲明的局部變量,要比建立一個已經定義過的局部變量慢9-10倍。
4.7 謹慎聲明全局變量
聲明一個未被任何一個函數使用過的全局變量,也會使性能降低。
這和聲明相同數量的局部變量一樣,PHP可能去檢查這個全局變量是否存在。
4.8 使用++$i遞增
當執行變量$i的遞增或遞減時,$i++會比++$i慢一些。
這種差異是PHP特有的,並不適用於其他語言,所以請不要修改你的C或Java代碼,並指望它們能立即變快,沒用的。
++$i更快是因爲它只需要3條指令(opcodes),$i++則需要4條指令。
後置遞增實際上會產生一個臨時變量,這個臨時變量隨後被遞增。
而前置遞增直接在原值上遞增。
4.9 不要隨便複製變量
有時候爲了使 PHP 代碼更加整潔,會把預定義好的變量,複製到一個名字更簡短的變量中。
其實這樣做的結果是增加了一倍的內存消耗,只會使程序更加慢。
// 不好的實踐
$description = $_POST['description'];
echo $description;
// 好的實踐
echo $_POST['description'];
4.10 循環內部不要聲明變量
尤其是大變量,這好像不只是PHP裏面要注意的問題吧?
4.11 一定要對變量進行初始化
5 數組
5.1 用字符串而不是數組作爲參數
如果一個函數既能接受數組,又能接受簡單字符做爲參數,那麼儘量用字符作爲參數。
5.2 數組元素加引號
$row['id']比$row[id]速度快7倍。
如果不帶引號,例如$a[name],那麼PHP會首先檢查有沒有define定義的name常量。
如果有,就用這個常量值作爲數組鍵值。如果沒有,再查找鍵值爲字符串'name'的數組元素。
5.3 多維數組操作
多維數組儘量不要循環嵌套賦值。
5.4 循環用foreach
儘量用foreach代替while和for循環,效率更高。