處理大量資料(如 50 萬筆日誌)時,單次載入全量陣列極易觸發 memory_limit。核心原則:**分批處理、用完即銷毀**。
<?php
ini_set('memory_limit', '64M');
set_time_limit(600);
$batchSize = 10000;
$handle = fopen($logFile, 'r');
while (!feof($handle)) {
$batch = [];
for ($i = 0; $i < $batchSize && !feof($handle); $i++) {
$batch[] = fgets($handle);
}
// 處理當前批次
processBatch($batch);
// 顯式釋放
unset($batch);
}
fclose($handle);
function processBatch(array $lines) {
foreach ($lines as $line) {
// 解析、統計、寫入 DB 等
}
}
?>
<?php
$s = str_repeat('1', 255); // 255 位元組
$m = memory_get_usage();
unset($s);
echo memory_get_usage() - $m; // 0,未釋放
$s = str_repeat('1', 256); // 256 位元組
$m = memory_get_usage();
unset($s);
echo memory_get_usage() - $m; // 272,已釋放
?>
<?php
$s = str_repeat('1', 256);
$p = &$s; // 建立引用
$m = memory_get_usage();
unset($s); // 僅銷毀 $s,$p 仍指向記憶體
echo memory_get_usage() - $m; // 0,未釋放
// 正確做法:同時銷毀所有引用
unset($s, $p); // 或 $s = null; $p = null;
// 此時記憶體才會釋放
?>
array_splice、Generator、資料庫游標)。unset 暫存變數。&),除非明確需要修改原值。__destruct() 或 unset($obj)。memory_limit 視專案需求,但不應作為唯一解法。