Analisi di file di text di grandi size con PHP senza uccidere il server

Sto provando a leggere alcuni file di text di grandi size (tra 50M-200M), facendo una semplice sostituzione del text (Essenzialmente il xml che ho non è stato correttamente scappato in alcuni casi regolari). Ecco una versione semplificata della function:

<?php function cleanFile($file1, $file2) { $input_file = fopen($file1, "r"); $output_file = fopen($file2, "w"); while (!feof($input_file)) { $buffer = trim(fgets($input_file, 4096)); if (substr($buffer,0, 6) == '<text>' AND substr($buffer,0, 15) != '<text><![CDATA[') { $buffer = str_replace('<text>', '<text><![CDATA[', $buffer); $buffer = str_replace('</text>', ']]></text>', $buffer); } fputs($output_file, $buffer . "\n"); } fclose($input_file); fclose($output_file); } ?> 

Quello che non capisco è che per il più grande dei file, circa 150mb, l'utilizzo della memory PHP va fuori dal grafico (circa 2 GB) prima di fallire. Ho pensato che questo fosse il modo più efficiente di memory per leggere file di grandi size. C'è qualche metodo che mi manca sarebbe più efficiente per la memory? Forse qualche impostazione che tiene le cose in memory quando dovrebbe essere raccolto?

In altre parole, non funziona e non so perché, e per quanto ne so non sto facendo le cose in modo errato. Qualche direzione per me di andare? Grazie per qualsiasi input.

PHP non è davvero progettato per questo. Scarica il lavoro su un altro process e chiamalo o avvialo da PHP. Suggerisco di usare Python o Perl .

Dalla mia scarsa comprensione della garbage collection di PHP, il seguente potrebbe aiutare:

  1. unset $buffer quando hai finito di scrivere su disco, dicendo esplicitamente al GC di pulirlo.
  2. metti il ​​block if in un'altra function, in modo che il GC funzioni quando quella function viene chiusa.

Il ragionamento dietro queste raccomandazioni è il sospetto che il garbage collector non stia liberando la memory perché tutto è fatto all'interno di una singola function, e il GC è spazzatura.

Mi aspetto che questo fallisca in molti casi. Stai leggendo in blocchi di 4096 byte. Chi sa che il cut-off non sarà nel mezzo di un <text> ? In tal caso il tuo str_replace non functionrebbe.

Hai preso in considerazione l'utilizzo di un'espressione regolare?