首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

深入解析 PHP strtr 函數效率與原始碼分析

     編輯:PHP 綜合知識

前言

在日常開發中,字串匹配與替換是常見操作。過去我習慣使用 str_replace 或 preg_replace,但聽說 strtr 效能不錯,決定實測比較並深入 PHP 原始碼一探究竟。

效能實測

測試環境:PHP 7.x,執行 1000 次迴圈,對 MD5 產生的字串進行替換。

$i = 0;
$t = microtime(true);
for(;$i<1000;$i++) {
    $str = strtr(md5($i), $p2);
}
var_dump(microtime(true)-$t); // 0.085476875305176

$t = microtime(true);
for(;$i<2000;$i++) {
    $str = preg_replace($p, '', md5($i));
}
var_dump(microtime(true)-$t); // 0.09863805770874

結果顯示,strtr 效率比 preg_replace 高約 15% 左右。

PHP 內核原始碼分析

strtr 函數入口

查看 PHP_FUNCTION(strtr) 實現,主要流程:

  1. 參數檢查(接受 2 或 3 個參數)
  2. 若為 2 參數且第二參數非陣列,拋出警告
  3. 將第一參數轉為字串
  4. 空字串快速返回
  5. 根據參數數量分發:
  • 2 參數(陣列模式):呼叫 php_strtr_array
  • 3 參數(字串模式):呼叫 php_strtr

核心實現:php_strtr(字串模式)

PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen)
{
    int i;
    unsigned char xlat[256];
    if ((trlen < 1) || (len < 1)) return str;

    // 初始化對應表:xlat[i] = i
    for (i = 0; i < 256; xlat[i] = i, i++);

    // 建立字元映射:from[i] -> to[i]
    for (i = 0; i < trlen; i++) {
        xlat[(unsigned char) str_from[i]] = str_to[i];
    }

    // 逐字元替換
    for (i = 0; i < len; i++) {
        str[i] = xlat[(unsigned char) str[i]];
    }
    return str;
}

此演算法建立 256 字元的查找表,時間複雜度 O(n + m),對單字元替換極高效。例如 strtr('abcdaaabcd', 'ab', 'efd') 輸出 efcdeeefcd(注意:'a'→'e', 'b'→'f', 'd' 保持不變)。

核心實現:php_strtr_array(陣列模式)

陣列模式支援多字元鍵值替換,採用「最長匹配優先」策略:

  1. 將替換陣列複製到臨時 HashTable,記錄鍵的最大/最小長度
  2. 從字串開頭掃描,每次取最大長度嘗試匹配
  3. 在 HashTable 中查找,找到則替換並跳過對應長度
  4. 未匹配則輸出原字元,位置前移 1
// 關鍵邏輯片段
while (pos < slen) {
    if ((pos + maxlen) > slen) maxlen = slen - pos;
    found = 0;
    memcpy(key, str+pos, maxlen);
    for (len = maxlen; len >= minlen; len--) {
        key[len] = 0;
        if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) {
            // 找到匹配,附加替換值,pos += len
            found = 1; break;
        }
    }
    if (!found) { smart_str_appendc(&result, str[pos++]); }
}

此設計確保 array('a'=>'e', 'ab'=>'f') 對 "abcd" 會優先匹配 "ab" 替換為 "f",而非先替換 "a"。

結論

  • 單字元替換:php_strtr 使用查找表,極快,適合大量單字元映射。
  • 多字元替換:php_strtr_array 採用最長匹配 + Hash 查找,邏輯嚴謹但開銷較大,鍵長度差異大時效能下降。
  • 避坑指南:盡量避免使用 strtr(string, string, string) 三參數形式,非單位元組字元易產生亂碼。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved