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

PHP 大量寫入檔案效能實測:fwrite 完勝 file_put_contents

     編輯:PHP 相關知識

需求:將 100 萬行資料寫入文字檔。實測 fwrite 僅需約 10 秒,file_put_contents (搭配 FILE_APPEND) 卻耗時 300 秒且漏寫資料。本文詳細記錄測試過程、程式碼與結論。

測試環境

  • PHP 7.x / 8.x (CLI 模式)
  • Windows / Linux 均可重現
  • 資料量:1,000 用戶 × 1,000 項目 = 1,000,000 行

測試程式碼:file_put_contents (失敗)

<?php
function microtimeFloat() {
    list($usec, $sec) = explode(' ', microtime());
    return (float)$usec + (float)$sec;
}

$userCount = 1000;
$itemCount = 1000;
$file = 'ratings.txt';

if (file_exists($file)) unlink($file);

$timeStart = microtimeFloat();
for ($i = 0; $i < $userCount; $i++) {
    $uid = bin2hex(random_bytes(16)); // 32 字元隨機 ID
    for ($j = 0; $j < $itemCount; $j++) {
        $itemId = mt_rand(1, 300000);
        $rating = $j === 0 ? 1 : mt_rand(1, 100) / 100;
        $line = sprintf("%s,%d,%.2f\n", $uid, $itemId, $rating);
        file_put_contents($file, $line, FILE_APPEND); // 每行開啟、寫入、關閉檔案
    }
}
$timeEnd = microtimeFloat();
echo "file_put_contents 耗時: " . ($timeEnd - $timeStart) . " 秒\n";
// 實測輸出: 307 秒,且檔案僅 999,997 行 (漏 3 行),過程中出現 Permission denied 警告
?>

測試程式碼:fwrite (成功)

<?php
function microtimeFloat() {
    list($usec, $sec) = explode(' ', microtime());
    return (float)$usec + (float)$sec;
}

$userCount = 1000;
$itemCount = 1000;
$file = 'ratings_fwrite.txt';

if (file_exists($file)) unlink($file);

$fp = fopen($file, 'ab'); // 以二進位附加模式開啟一次
if (!$fp) die("無法開啟檔案: $file");

$timeStart = microtimeFloat();
for ($i = 0; $i < $itemCount; $i++) { // 為了測試速度調整迴圈順序
    $uid = bin2hex(random_bytes(16));
    for ($j = 0; $j < $userCount; $j++) {
        $itemId = mt_rand(1, 300000);
        $rating = $j === 0 ? 1 : mt_rand(1, 100) / 100;
        $line = sprintf("%s,%d,%.2f\n", $uid, $itemId, $rating);
        fwrite($fp, $line);
    }
}
fclose($fp);
$timeEnd = microtimeFloat();
echo "fwrite 耗時: " . ($timeEnd - $timeStart) . " 秒\n";
// 實測輸出: 10.7 秒,檔案完整 1,000,000 行
?>

效能差異分析

指標file_put_contents + FILE_APPENDfwrite (資源控制代碼)
系統呼叫次數1,000,000 次 (每行 open/write/close)1 次 open + 1,000,000 次 write + 1 次 close
檔案鎖定/解鎖每行各一次僅開啟/關閉時
緩衝機制無使用者層級緩衝,依賴 OSPHP 內部緩衝 (預設 8KB),批量寫入磁碟
錯誤率高併發下易發生 Permission denied、資料遺失極低,單一控制代碼管理
實測耗時~307 秒~10 秒
資料完整性漏寫完整

最佳實踐建議

  1. 大量寫入、日誌記錄、資料匯出:務必使用 fopen + fwrite + fclose。
  2. 高併發環境:配合 flock($fp, LOCK_EX) 獨佔鎖定,寫入後 flock($fp, LOCK_UN) 釋放。
  3. 超大資料 (GB 級):考慮分批寫入、使用 stream_set_chunk_size() 調整緩衝、或直接用資料庫 LOAD DATA INFILE / COPY 批量導入。
  4. 小量、單次寫入:file_put_contents 程式碼簡潔,效能差異可忽略,可使用。

進階:使用 SplFileObject (物件導向封裝)

<?php
$file = new SplFileObject('data.txt', 'wb'); // 寫入模式,自動處理關閉
$file->setFlags(SplFileObject::DROP_NEW_LINE); // 不自動加換行

for ($i = 0; $i < 1000000; $i++) {
    $file->fwrite("第 $i 行資料\n");
}
// 物件銷毀時自動 fclose
?>

SplFileObject 內部同樣使用緩衝寫入,效能接近 fwrite,程式碼更現代化且自動資源管理。

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