2017-08-27 2 views
0

Ich lese eine 45Mb Textdatei in NodeJS und einige Verarbeitung für jedes Zeichen darauf.Warum verursacht ein Nodejs Write Stream einen zunehmenden Speicherverbrauch?

Die erste Version meines Skripts nahm ein Zeichen aus der ursprünglichen Datei, speichert es in einer Akkumulatorvariablen (Ergebnis + = char) und speichert dann das Ergebnis in einer Textdatei. Dies funktioniert nicht, da die Datei so groß war, dass ich zu viele Daten in den RAM speicherte. Daher habe ich einen Fehler bekommen: Javascript Heap out of memory. Ich beschloss, einen Schreibstrom zu verwenden, so dass ich die Daten direkt auf der Festplatte einen Chat zu der Zeit schreiben kann, so das das Problem lösen könnte:

fs = require('fs'); 

var proportion = 2; 

var c = ''; 

fs.readFile('./concat/all.txt', 'utf8', function (err,data) { 
    if (err) { 
     return console.log(err); 
    } 

    var h = parseInt(Math.sqrt(data.length/proportion)); 
    var w = parseInt(h * proportion); 

    console.log(w, h); 

    var wstream = fs.createWriteStream('output.txt'); 


    var lineCount = 0; 
    for(var x = 0; x < data.length; x++) { 

     if(data.charCodeAt(x) === 32 && x > 0 && data.charCodeAt(x - 1) === 32) 
      continue; 

     if(data.charCodeAt(x) === 10 && x > 0 && data.charCodeAt(x - 1) === 10) 
      continue; 

     c = (data.charCodeAt(x) === 10 || data.charCodeAt(x) === 13 || data.charCodeAt(x) === 9) ? " " : data.charAt(x); 
     lineCount++; 
     if(lineCount > w) { 
      c += "\n"; 
      lineCount = 0; 
     } 


     wstream.write(c); 
    } 

    wstream.end(); 

}); 

Aber immer noch, ich bin nicht genügend Arbeitsspeicher Fehler. Das Skript läuft ohne Probleme, wenn ich wstream.write(c) kommentiere. Warum?

+0

ich denke, da Ihre for-Schleife endet in vielleicht 1 Sekunde und das Schreiben dauert immer noch 100 Sekunden. also im Grunde ist es immer noch alles in Erinnerung ... Sie müssen Ihre 'wstream.write (c);' -Aufrufe verlangsamen. –

+0

... ich würde sogar sagen, das erste Zeichen wird nur geschrieben, nachdem Sie Ihren ReadFile-Callback beendet haben. und davor werden alle Daten, die Sie schreiben möchten, im Speicher zwischengespeichert. –

+0

Also? Ist meine Lösung wie ** Crossplatform **? – EMX

Antwort

1

-Stream, Stream, Stream ...

Drosselklappen die I/O:

Strom, der den Eingang in Chunks für jeden Chunk, den Strom unterbrechen, parsen & jedes Zeichen des aktuellen chunk manipulieren und schreibe es in die Ausgabe.

Dann können Sie den Eingangsstrom fortsetzen, um mit dem nächsten fortzufahren, wiederholen bis zum Ende.


hatte ich kein Problem mit Ihrem Code Drosselung mit createReadStream & createWriteStream

Hier ist der Code (erfolgreich getestet mit einer 64MB Datei)

const fs = require('fs') 
var w; var charCount = 0; var proportion = 2 
//:This step was required to populate 'w' 
fs.readFile('input.txt', 'utf8', function (err,data) { 
if(err){return console.log(err)} 
let h = parseInt(Math.sqrt(data.length/proportion)) 
w = parseInt(h * proportion); data = undefined; 
console.log('[+] starting (w:',w,')'); EMX() 
}); 
//:Here is the magick 
function EMX(){ 
const I = fs.createReadStream('input.txt') 
const O = fs.createWriteStream('output.txt') 
I.on('end',()=>{console.log("[+] operation completed")}) 
I.on('data', (chunk) => { 
    I.pause(); let data = chunk.toString() 
    for(var x=0;x<data.length;x++){ 
    if(data.charCodeAt(x) === 32 && x > 0 && data.charCodeAt(x - 1) === 32) continue 
    if(data.charCodeAt(x) === 10 && x > 0 && data.charCodeAt(x - 1) === 10) continue 
    c = (data.charCodeAt(x) === 10 || data.charCodeAt(x) === 13 || data.charCodeAt(x) === 9) ? " " : data.charAt(x) 
    if(charCount>w){c+="\n";charCount=0;} charCount++ 
    O.write(c) 
    } 
    I.resume() 
}) 
} 
Verwandte Themen