延續上篇原始碼分析,實測三種函數在不同模式下的效能表現。測試字串長度約 80 字元,執行 10,000 次迴圈。
$str = '111111110000000000000000000000000000000111000001000100010000010010000010010000010100000010';
$str = str_repeat($str, 1); // 重複 1 次或 8 次模擬不同長度
$pattern1 = array('12345'=>'', '67891'=>''); // 短鍵
$pattern2 = array('a'=>'', '1234567890'=>''); // 長短鍵混雜
$pattern3 = '/12345|67891/';
$pattern4 = '/a|1234567890/';
$pattern5 = array('12345', '67891');
$pattern6 = array('a', '1234567890');
// 註釋中第一個數字為 repeat=1,第二個為 repeat=8
$t = microtime(true);
for($i=0; $i<10000; $i++) strtr($str, $pattern1);
echo microtime(true)-$t, "/n"; // 0.219 / 0.473
$t = microtime(true);
for($i=0; $i<10000; $i++) strtr($str, $pattern2);
echo microtime(true)-$t, "/n"; // 0.477 / 2.726
$t = microtime(true);
for($i=0; $i<10000; $i++) preg_replace($pattern3, '', $str);
echo microtime(true)-$t, "/n"; // 0.305 / 1.086
$t = microtime(true);
for($i=0; $i<10000; $i++) preg_replace($pattern4, '', $str);
echo microtime(true)-$t, "/n"; // 0.303 / 1.117
$t = microtime(true);
for($i=0; $i<10000; $i++) str_replace($pattern5, '', $str);
echo microtime(true)-$t, "/n"; // 0.180 / 0.225
$t = microtime(true);
for($i=0; $i<10000; $i++) str_replace($pattern6, '', $str);
echo microtime(true)-$t, "/n"; // 0.181 / 0.231
| 函數 | 短字串 (repeat=1) | 長字串 (repeat=8) | 備註 |
|---|---|---|---|
| str_replace | 0.180 / 0.181 | 0.225 / 0.231 | 整體表現最佳,穩定 |
| preg_replace | 0.305 / 0.303 | 1.086 / 1.117 | 正則引擎開銷大,長字串明顯變慢 |
| strtr (短鍵) | 0.219 | 0.473 | 尚可,但隨鍵長度差異增大效能急劇下降 |
| strtr (長短鍵混雜) | 0.477 | 2.726 | 最差,因需從最大長度遞減嘗試匹配 |
查看原始碼可知,str_replace(array search, mixed replace, string subject) 會依 search 陣列順序逐一掃描 subject,找到即替換。無「最長匹配」邏輯,無額外長度循環,故效能優異。
str_replace(array('ab', 'abc'), '1', 'abcd'); // 輸出 "1cd"
// 先匹配 'ab' 替換為 '1',剩餘 'cd' 不再匹配 'abc'
strtr(array('ab'=>'1', 'abc'=>'1'), 'abcd'); // 輸出 "1d"
// 採最長匹配優先,'abc' 先匹配替換為 '1',剩餘 'd'
注意:str_replace 依陣列順序匹配,若需優先替換長鍵,請手動調整陣列順序(長鍵在前)。
strtr($str, $from, $to) 處理多位元組字元(易亂碼)。