處理大檔案時最大限度地減少記憶體使用量

如果我們需要解析一個大檔案,例如一個包含數百萬行的超過 10 MB 的 CSV 檔案,有些人會使用 filefile_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 在每個迴圈中被覆蓋。