處理大檔案時最大限度地減少記憶體使用量
如果我們需要解析一個大檔案,例如一個包含數百萬行的超過 10 MB 的 CSV 檔案,有些人會使用 file
或 file_get_contents
函式,最後點選 memory_limit
設定
允許的記憶體大小為 XXXXX 位元組耗盡
錯誤。考慮以下來源(top-1m.csv 正好有 100 萬行,大小約為 22 MB)
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
這輸出:
int(262144)
int(210501632)
因為直譯器需要儲存 $arr
陣列中的所有行,所以它消耗了大約 200 MB 的 RAM。請注意,我們甚至沒有對陣列的內容做任何事情。
現在考慮以下程式碼:
var_dump(memory_get_usage(true));
$index = 1;
if (($handle = fopen("top-1m.csv", "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
file_put_contents('top-1m-reversed.csv',$index . ',' . strrev($row[1]) . PHP_EOL, FILE_APPEND);
$index++;
}
fclose($handle);
}
var_dump(memory_get_usage(true));
哪個輸出
int(262144)
int(262144)
所以我們不使用單個額外的記憶體位元組,而是解析整個 CSV 並將其儲存到另一個檔案中,以反轉第二列的值。那是因為 fgetcsv
只讀取一行,而 $row
在每個迴圈中被覆蓋。