Ich stellte versehentlich fest, dass bei React auf dem Server NODE_ENV! = Produktion verursacht wird. Spezifische Probleme: https://github.com/facebook/react/issues/7406. Mit der weit verbreiteten Verwendung von Knoten und reagieren Isomorphismus und anderen Technologien sollten Probleme wie die Leckage des Knoten-Seiten-Speichers unsere Aufmerksamkeit auf sich ziehen. Warum ist der Knoten anfällig für Speicherlecks und wie kann man nach dem Auftreten von Fehlerbehebung beheben? Das Folgende ist eine kurze Einführung und ein kurzes Beispiel.
Erstens basiert der Knoten auf der V8 -Engine und seine Speicherverwaltungsmethode stimmt mit V8 überein. Das Folgende ist eine kurze Einführung in die relevanten Gedächtniseffekte von V8.
V8 Speichergrenze
Der Knoten ist auf V8 aufgebaut und kann JS -Objekte über V8 zuweisen und verwalten. V8 hat Einschränkungen bei der Speicherverwendung (ca. 1,4 g für die alte Generation von Speicher 64-Bit-System, etwa 0,7 g für das 32-Bit-System, etwa 32 MB für die neue Generation von Speicher 64-Bit-System und etwa 16 MB für das 32-Bit-System). Unter solchen Einschränkungen können große Speicherobjekte nicht funktionieren. Wenn Sie diese Grenze versehentlich berühren, wird der Prozess beendet.
Ursache: V8 blockiert die JavaScript-Anwendungslogik bei der Ausführung von Müllsammlung und führt dann die JavaScript-Anwendungslogik erneut aus, bis die Müllsammlung vorbei ist. Dieses Verhalten heißt "Stop-the-World". Wenn der Heap-Speicher von V8 1,5 GB beträgt, dauert es mehr als 50 ms für V8, um eine kleine Müllsammlung durchzuführen, und es dauert mehr als 1 Sekunde für eine nicht inkrementelle Müllsammlung.
Stellen Sie den Speicher der neuen Generation und den Speicher der alten Generation ein, um die Standardspeichergrenze zu knacken, indem Sie Knoten-Max-alte Space-Größe = XXX (Einheit MB) und Knoten-Max-New-Space-Größe = xxx (Einheit KB) einstellen.
V8 Heap -Komposition
Der V8 -Haufen besteht nicht tatsächlich aus zwei Teilen: der alten Generation und der neuen Generation. Der Haufen kann in mehrere verschiedene Regionen unterteilt werden:
GC Recycling -Typ
Inkrementelle GC
Gibt an, ob der Müllsammler beim Scannen von Speicherplatz Müll sammelt (fügt) Müll und löscht am Ende des Scan -Zyklus den Müll.
Nicht-inkrementeller GC
Bei Verwendung eines nicht-inkrementellen Müllsammlers ist der Müll leer, sobald er gesammelt wird.
Der Garbage Collector wird nur Müllsammlung für den Speicherbereich der neuen Generation, den Zeigerbereich der alten Generation und den Datenbereich der alten Generation durchführen. Das Objekt tritt zunächst in den Speicher der neuen Generation ein, der weniger Platz einnimmt. Die meisten Objekte scheitern schnell, und nicht inkrementeller GC recycelt diese kleinen Mengen an Speicher direkt. Wenn einige Objekte für einen bestimmten Zeitraum nicht recycelt werden können, werden sie in den Speicherbereich der alten Generation eingegeben. Dieser Bereich führt selten inkrementelle GC aus und dauert lange.
Wann tritt dann das Speicherleck auf?
Speicherleckpfade
Die Speicherzusammensetzung des Knotens ist hauptsächlich der Teil, der durch V8 zugewiesen wird, und der Teil, der vom Knoten selbst zugewiesen wird. Die Hauptbeschränkung der Müllsammlung von V8 ist der Heap -Speicher von V8. Die Hauptgründe für Speicherlecks: 1. Cache; 2. Die Warteschlangenkonsum ist nicht rechtzeitig; 3. Umfang nicht freigegeben
Speicherleckanalyse
Überprüfen Sie den V8 -Speicherverbrauch (Einheitsbyte)
process.memoryusage (); {ress: 47038464, heaptotal: 34264656, gehackt: 2052866}Ress: Der ansässige Speicherteil des Prozesses
heaptotal, gehackt: V8 Heap -Speicherinformationen
Überprüfen Sie die Systemspeicherverwendung (Einheits -Byte)
os.totalmem()
os.freemem ()
Gibt den gesamten Systemspeicher und den Leerlaufspeicher zurück
Müllsammlungsprotokoll anzeigen
Node --Trace_GC -e "var a = []; für (var i = 0; i <1000000; i ++) {A.push (New Array (100));}" >> gc.log // Ausgabe von Müllsammlungs -Protokoll
Node -Prof // Ausgabeknotenausführungsleistungsprotokoll. Verwenden Sie Windows-Tick.Processor, um anzuzeigen.
Analytische Überwachungsinstrumente
V8-Profiler erfasst Schnappschüsse des V8-Heap-Speichers und analysiert die CPU
Node-heapdump greift Schnappschüsse des V8-Heap-Speichers ab
Node-Mtrace-Analyse-Stapelverbrauch
Node-Memwatch hört auf die Situation der Müllsammlung zu
Node-Memwatch
memwatch.on ('stats', function (info) {console.log (info)}) memwatch.on ('leck', function (info) {console.log (info)})STATS -Ereignis: Jedes Mal, wenn eine vollständige Haufen Müllsammlung durchgeführt wird, wird das Statistik -Ereignis ausgelöst. Dieses Ereignis wird Speicherstatistiken bestehen.
oder 2499912, // Minimum "max": 2592568, // maximal "useage_trend": 0 // Benutzertrend}
Beobachten Sie num_full_gc und num_inc_gc reflektieren die Müllsammlung.
Leckereignis: Wenn der Speicher nach 5 aufeinanderfolgenden Müllsammlungen noch nicht freigegeben wird, bedeutet dies, dass Speicherlecks auftreten. Diesmal wird ein Leckereignis ausgelöst.
{Start: Fr, 29. Juni 2012 14:12:13 GMT, Ende: Fr, 29 Jun 2012 14:12:33 GMT, Wachstum: 67984, Grund: 'Heap -Wachstum über 5 aufeinanderfolgende GCs (20S) - 11,67 MB/HR'}Heap Diffing Heap Speicher Vergleichsvergleichsbehebung Speicherüberlaufcode.
Im Folgenden verwenden wir ein Beispiel, um zu demonstrieren, wie Sie Speicherlecks beheben können:
Zuerst erstellen wir ein Beispiel, das Speicherlecks verursacht:
//app.jsvar app = require('express')();var http = require('http').Server(app);var heapdump = require('heapdump');var leakobjs = [];function LeakClass(){ this.x = 1;}app.get('/', function(req, res){ console.log('get /'); for(var i = 0; i <1000; function () {console.log ('auf Port 3000');});Hier simulieren wir Speicherlecks, indem wir ein Array einrichten, das ständig zunimmt und nicht abgerufen wird.
Verwenden Sie das Heap-Dump-Modul, um Speicher-Snapshots regelmäßig aufzunehmen, und importieren Sie Schnappschüsse über die Chrome Developer Tool-Toolprofile zum Vergleich und Analyse.
Wir können sehen, dass nach dem Zugriff auf Localhost: 3000 der Browser und die Größe des Schnappschusss um ein Vielfaches erfrischt, und selbst wenn dies nicht angefordert wird, nimmt dies nicht ab, was darauf hinweist, dass ein Leck aufgetreten ist.
Anschließend importieren wir Schnappschüsse über die Chrome Developer Tool -Toolprofile. Vergleichen Sie durch Einstellen des Vergleichs den ersten Schnappschuss, senden Sie Anfragen und senden Sie dann Anforderungen, um Speicher -Snapshots in diesen drei Stufen zu senden. Sie können feststellen, dass die Leckklasse auf der rechten Seite zugenommen hat. Im Delta immer positiv, bedeutet es, dass es nicht recycelt wurde.
Zusammenfassung
Bei Speicherlecks können Sie MemWatch verwenden, um den Prozess zu implantieren oder den Prozess zu melden.
Wenn Speicherlecks gefunden werden, können Sie, falls dies zulässig ist, die Knoten-Heapdump-lokal ausführen und zeitgesteuerte Speicherschnappschüsse verwenden, um zu erzeugen. Und verwenden Sie den Schnappschuss, um die Ursache der Leckage durch Chromprofile zu analysieren. Wenn lokales Debuggen nicht möglich ist, verwenden Sie V8-Profiler, um Speicher-Snapshots auf dem Testserver auszugeben, um JSON zu vergleichen und zu analysieren (Code-Intrusion ist erforderlich).
Unter welchen Umständen ist Memwatch/Heapdump aktiviert. Betrachten Sie die Häufigkeit von Heapdump, um zu vermeiden, dass die CPU ausgeht. Andere Möglichkeiten, das Gedächtniswachstum zu erkennen, können ebenfalls berücksichtigt werden, z. B. den direkten Überwachungsprozess.MemoryUSage ().
Vorsicht vor Fehleinschätzungen, Kurzzeitgedächtnisnutzungspeaks verhalten sich wie Speicherlecks. Wenn Ihre App plötzlich viel CPU und Speicher verbraucht, kann die Verarbeitungszeit mehrere Müllansammlungszyklen umfassen, und dann kann Memwatch sie als Speicherleck falsch einschätzen. In diesem Fall fällt der Speicherverbrauch jedoch, sobald Ihre App diese Ressourcen verwendet, wieder auf das normale Niveau. Es ist daher wichtig zu beachten, dass Speicherlecks kontinuierlich gemeldet werden und ein oder zwei plötzliche Alarme ignoriert werden können.