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

PHP 性能優化實戰:require/include vs 文件緩存序列化,快 3.4 倍

     編輯:PHP 相關知識

實測場景

  • 數據:3 萬元素陣列,序列化後 1MB 文本文件。
  • 操作:循環 100 次載入。
  • 環境:PHP 5.x / Apache (當時測試環境),結論在 PHP 7/8 依然成立。

方案對比

方案 A:require 'array.php' (PHP 代碼文件)

<?php
// array.php
return [
    'key1' => 'value1',
    // ... 30,000 元素
];
?>
<?php
for ($i = 0; $i < 100; $i++) {
    $arr = require __DIR__ . '/array.php';
}
// 平均耗時:12.89 秒

方案 B:unserialize(file_get_contents('array.txt')) (序列化文件)

<?php
// 生成緩存文件 (一次性)
file_put_contents('array.txt', serialize($hugeArray));

// 運行時載入
for ($i = 0; $i < 100; $i++) {
    $arr = unserialize(file_get_contents(__DIR__ . '/array.txt'));
}
// 平均耗時:3.80 秒

核心結論

指標require/includefile_get_contents + unserialize提升
耗時12.89s3.80s3.4x 更快
原理詞法分析 → 語法分析 → 編譯 opcode → 執行讀文件 → 反序列化 (C 級循環)
內存峰值高 (編譯過程佔用)低 (直接構建陣列)

為什麼 require 慢?

  1. 完整編譯流程:PHP 必須將文件解析為 AST、生成 opcode,即使 opcode 緩存 (OPcache) 命中,仍需驗證時間戳、解析返回語句。
  2. 陣列字面量開銷:['k'=>'v', ...] 執行時逐個插入哈希表,涉及大量內存分配與鍵哈希計算。
  3. 反序列化優化:unserialize 是 C 實現的專用解析器,直接按二進制格式構建 zval,無中間語法樹。

生產級緩存策略最佳實踐

1. 靜態配置/大陣列:序列化文件 + OPcache

<?php
function loadConfig(string $name): array {
    $cacheFile = sys_get_temp_dir() . "/app_config_{$name}.cache";
    $sourceFile = __DIR__ . "/config/{$name}.php";

    // 開發環境:源文件變化自動更新
    if (APP_DEBUG || !file_exists($cacheFile) || filemtime($sourceFile) > filemtime($cacheFile)) {
        $config = require $sourceFile;
        file_put_contents($cacheFile, serialize($config), LOCK_EX);
        return $config;
    }
    return unserialize(file_get_contents($cacheFile));
}
?>

2. 數據庫查詢結果緩存:igbinary/msgpack + Redis/文件

<?php
// 安裝:pecl install igbinary
$cacheKey = 'user:profile:' . $uid;
$data = Redis::get($cacheKey);
if ($data === false) {
    $data = $db->query("SELECT * FROM user_profile WHERE uid=?", $uid);
    Redis::setex($cacheKey, 3600, igbinary_serialize($data));
} else {
    $data = igbinary_unserialize($data);
}
?>
igbinary 比 serialize 快 2-3 倍、體積減 30-50%;msgpack 更快、跨語言。

3. 安全性:將緩存目錄移出 Web 根目錄

# 目錄結構
/var/www/app/          # Web 根目錄
/var/www/app/data/     # 緩存目錄 (不可直接訪問)
/var/www/app/public/   # 真正 DocumentRoot

# .htaccess in /var/www/app/data/
deny from all

常見框架現狀

  • Discuz! / Sablog (舊版):緩存為可 require 的 PHP 文件 (歷史包袱)。
  • Laravel / Symfony / ThinkPHP 現代版:配置緩存 php artisan config:cache 生成單文件 bootstrap/cache/config.php (實際是 return unserialize(...) 形式)。
  • Composer Classmap:composer dump-autoload -o 生成陣列映射,本質同理。

總結

大數據結構緩存:拒絕 require PHP 文件,擁抱序列化文件/Redis + 高效序列化器。這不僅快 3 倍以上,還能將緩存目錄隔離在 Web 根目錄外,兼顧安全。下次見到 var_export($arr, true) 寫入 .php 緩存,請果斷重構為 serialize() / igbinary_serialize()。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved