Ich erzeuge eine ~ 200000-Element-Array von Objekten (mit Objekt Literal Notation innerhalb map
statt new Constructor()
), und ich bin Speichern einer JSON.stringify
'd-Version davon auf der Festplatte, wo es 31 MB, einschließlich Zeilenumbrüche und Ein-Platz-pro-Einzug Ebene (JSON.stringify(arr, null, 1)
).JSON.parse() auf einem großen Array von Objekten verwendet viel mehr Speicher als es sollte
Dann wird in einem neuen Knoten Prozess, las ich die gesamte Datei in eine UTF-8-String und übergeben es an JSON.parse
:
var fs = require('fs');
var arr1 = JSON.parse(fs.readFileSync('JMdict-all.json', {encoding : 'utf8'}));
Knoten Speicherverbrauch etwa 1,05 GB ist nach Mavericks' Activity Monitor! Selbst wenn ich in ein Terminal tippe, fühle ich mich auf meiner uralten 4-GB-RAM-Maschine lahm.
Wenn aber in einem neuen Knoten Prozess, ich die Inhalt in einen String der Datei zu laden, hacken sie an Elementgrenzen auf und JSON.parse
jedes Element einzeln, angeblich immer das gleiche Objekt Array:
var fs = require('fs');
var arr2 = fs.readFileSync('JMdict-all.json', {encoding : 'utf8'}).trim().slice(1,-3).split('\n },').map(function(s) {return JSON.parse(s+'}');});
Knoten verwendet nur ~ 200 MB Arbeitsspeicher und keine merkliche Systemverzögerung. Dieses Muster bleibt bei vielen Neustarts des Knotens bestehen: JSON.parse
Das gesamte Array erfordert eine Menge Speicher, während das parsen elementweise viel speichereffizienter ist.
Warum ist die Speicherbelegung so groß? Ist das ein Problem mit JSON.parse
verhindern effiziente Bildung versteckter Klassen in V8? Wie kann ich eine gute Speicherleistung erzielen, ohne Saiten zu schneiden und zu schneiden? Muss ich ein Streaming-JSON-Parser verwenden?
Zum leichteren Experimentieren habe ich die JSON-Datei in Frage gestellt in einer Gist, bitte zögern Sie nicht, es zu klonen.
Der von einem Prozess verbrauchte Speicher bedeutet nichts. Buchstäblich können Sie nicht über Ihre Verbrauchseffizienz des Code-Speichers basierend darauf begründen. – zerkms
@zerkms danke, dass du das herausgibst. Ich hätte feststellen müssen, dass sich mein System (4 GB physikalischer RAM) tatsächlich lustvoller anfühlt, sobald ich die erste Methode ausprobiere: Ich kann es sogar beim Tippen im Terminal erkennen. –
Huh. Wenn ich 'node --expose-gc' starte, führe das erste Code-Snippet aus (nutze 1 GB Speicher) und führe' global.gc(); 'aus. Etwa fünfzig Mal sinkt die Speicherbelegung des Knotens langsam auf 100 MB ab. Die Implikationen - wow. –