2015-02-04 6 views
6

Ich bin verwirrt, wie meine Anwendung Speicher leckt. Es ist ein TCP-Server, der Hunderttausende Pakete pro Minute verarbeitet. Ich habe den Code überprüft, verbessert und das Gedächtnis profiliert.node.js v8 Garbage Collection scheint nicht zu triggern

Alles scheint in Ordnung, testet lokal mit wenig Verkehr tatsächlich zeigt, dass die GC den Speicher ordnungsgemäß freigibt. Aber wenn es auf dem Live-Schwerverkehrsserver ist, tut es das nicht.

Also habe ich versucht mit der expose-gc Option und fügte die erzwungene GC zu jeder Trennung und jetzt habe ich festgestellt, dass der Speicher nicht mehr leckt oder war es jeder sogar undicht?

Also, meine Schlussfolgerung ist die GC hat nicht aktiviert. Mein Server hat 3 GB Speicher und die Anwendung in nur wenigen Stunden bekommt 2,8 GB davon.

Jetzt mit der erzwungenen GC ist die Anwendung nicht mehr undicht. Es hält rund 200 MB Speicher.

Also, meine Frage, warum wurde das GC nicht ausgelöst?

+0

Haben Sie schon einmal eine Lösung gefunden? Ich habe das gleiche Problem T_T –

+1

@MarsZhu Sorry, gab ich auf Node, und stattdessen Go, beste Entscheidung aller Zeiten. – majidarif

Antwort

1

Source: StrongLoop Blog

Die grundlegende Garbage Collection Problem löst, ist tot Speicherbereiche (unerreichbare Objekte/Müll), die durch irgendeine Kette von Zeigern von einem Objekt nicht erreichbar sind zu identifizieren, die unter Spannung steht. Sobald identifiziert, können diese Regionen für neue Zuweisungen oder freigegeben zurück an das Betriebssystem

Das Austreten von Speichern wiederverwendet werden bei der Verwendung von Hörern Ereignis ist durchaus üblich und wird durch eine Situation verursacht, in dem das Objekt, das ist es wird verhindert, dass das Abhören von Datenmüll erfasst wird, da der Ereignisemitter, auch ein Objekt, einen Verweis darauf behält.

Also in Ihrem Code onSuccess Methode wird durch Ihre Anfrage Objekt verwiesen werden. Das onSuccess ist jedoch nur eine Funktion, die als ein Listener für alle Anforderungsobjekte wiederverwendet wird, so dass das nicht zu Speichererweiterung führen sollte.

Um die wirkliche Ursache für Objekte zu finden, die in Ihrem Code belassen werden, würde ich nach der Verbindungsbeendigung suchen und sicherstellen, dass keine Zeiger am Leben bleiben. Außerdem erstellt V8 in einigen Fällen keine Instanz einer Funktion für jedes Mal, wenn es verwendet wird, und dies kann der Fall sein. Wenn beide kombiniert werden, wird der zugewiesene Speicher Instanzen des Rückrufs anhäufen.

Objekte, die zwei kleinere Müllsammlungen überlebt haben, werden gefördert zu „old-Raum.“ Old-Raum ist Müll in voller GC gesammelt (major Garbage Collection-Zyklus), die viel weniger häufig. Ich nehme an, dass ist weit hergeholt, aber die Option, die Sie schneller als Kehren Zyklen zuordnen könnte in Betracht gezogen werden, und damit, wenn Sie Müll Sammlung manuell auslösen, wird eine vollständige GC-Zyklus ausgelöst.

Um eine schnelle Objektzuordnung, kurze Garbage Collection Pausen und die „keine Speicherfragmentierung V8“ verwendet einen Stop-the-world, Generationen, genau, Garbage Collector zu gewährleisten. V8 stoppt im Wesentlichen die Ausführung des Programms , wenn ein vollständiger Speicherbereinigungszyklus ausgeführt wird.

Dies kann erklären, warum der Speicher nicht ausläuft, wenn V8 zur Müllreinigung gezwungen wird.

+2

Das ist verwirrend, nicht zu erwähnen, exakte Absätze von [Strongloops] (http://strongloop.com/strongblog/node-js-performance-garbage-collection/) Blog zu nehmen. – majidarif

+0

Stimmt, ich entschuldige mich dafür, dass ich die Quelle nicht hinzugefügt habe. Normalerweise mache ich das. – Selfish

+0

Nur der letzte Teil dieser Antwort ist relevant für die Frage! "Objekte, die zwei kleinere Garbage-Collections überlebt haben, werden zu" Old-Space "hochgestuft. Old-Space ist Garbage Collection in vollem GC (großer Garbage Collection-Zyklus), der viel seltener ist. Ich nehme an, dass dies weit hergeholt ist, aber die Option Wenn Sie die Speicherbereinigung manuell auslösen, wird ein vollständiger GC-Zyklus ausgelöst. " –

0

Ich merke das gleiche Problem mit Garbage Collection nicht passiert. Das Testen meines Servers, der den gleichen Inhalt (wiederholt von react) wiederholt in einen Testskriptspeicher eingibt, würde in einer Stunde oder so erschöpft sein. Diese AWS-Instanz hat nur 1 GB RAM.

Nach dem Erzwingen der Garbage Collection, sobald der HeapUsed 256MB überschritten hat, funktioniert alles stundenlang gut. HeapUsed oszilliert von etwa 150 MB nach einem GC auf etwas mehr als 256 MB.

Inzwischen stabilisiert sich heapTotal schließlich bei etwa 340MB.

Meine Schlussfolgerung ist, dass mein Server Speicher nicht verliert, Garbage Collection nicht wie erwartet stattfindet. Hier

ist, was ich tue:

setInterval (function() { 
    let mu = process.memoryUsage(); 
    console.log('heapTotal:', mu.heapTotal, 'heapUsed:', mu.heapUsed); 
    if (mu.heapUsed > 256 * 1024 * 1024) { 
     console.log('Taking out the garbage'); 
     global.gc(); 
    } 
}, 1000 * 60); 

Es wäre vielleicht besser sein Gedächtnis nach jeder Anfrage zu überprüfen.