2016-03-28 3 views
4

Ich benutze spawn-Kind Npm-Paket, um eine Shell zu erzeugen, wo ich eine binäre Datei ausführen, die ursprünglich auf C++ gebaut wurde. Ich gebe Stdins zu der Binärdatei und dann würde die Binärdatei die Stdouts ständig für jede Sekunde aussenden. Auf dem Node-Teil, sobald ich die Stdout von binary empfange, habe ich einen on Listener, der ungefähr wie stdout.on('data', function (data) {}) aussehen würde, wo ich diese Daten an den SSE-Kanal sende.Node.js virtueller Speicher erhöht ständig während der Verwendung von Kind-Prozess

Alles funktioniert gut, aber die Hauptsorge ist das konstante Speicherwachstum des Knotenprozesses, das ich sehe, wenn ich die Binärdatei jedes Mal mit einem Stdin triff. Ich habe skizziert, wie mein Code aussieht, gibt es eine elegante Möglichkeit, dieses Speicherwachstum zu kontrollieren, wenn ja, bitte teilen.

var sseChannel = require('sse-channel'), 
 
    spawnCommand = require('spawn-command'), 
 
    cmd = 'path to the binary file', 
 
    globalArray = [], 
 
    uuid = require('uuid'); 
 

 
module.exports = function(app) { 
 
    var child = spawnCommand(cmd), 
 
    privateChannel = new sseChannel({ 
 
     historySize: 0, 
 
     cors: { 
 
     origins: ['*'] 
 
     }, 
 
     pingInterval: 15 * 1000, 
 
     jsonEncode: false 
 
    }); 
 
    srvc = { 
 
    get: function(req, res) { 
 
     globalArray[uuid.v4()] = res; 
 
     child.stdin.write('a json object in a format that is expected by binary' + '\n'); // req.query.<queryVal> 
 
     child.stdout.on('data', function(data) { 
 
     privateChannel.send(JSON.stringify(data)); 
 
     }); 
 
    }, 
 
    delete: function(sessionID) { 
 
     var response = globalArray[sessionID]; 
 
     privateChannel.removeClient(response); 
 
     response.end(); 
 
     delete globalArray[sessionID]; 
 
    } 
 
    } 
 
}

ist dieser Code nur aufzuzählen, wie es in der App aussehen würde. Das Ausführen des Code-Snippets würde in diesem Fall nicht funktionieren.

Ich sammelte heapdump in 2 verschiedenen Intervallen und dies ist, wie die Statistik sieht, gibt es eine enorme Steigerung in dem Array-Wert typisiert ist, was getan werden könnte, zu erhalten oder das Wachstum von typisierten Array unterdrücken,

enter image description here

enter image description here

+0

Rufen Sie 'srvc.get()' mit jeder Anforderung? – mscdex

+0

Ja, das ist richtig. Jedes Mal, wenn eine Anfrage gemacht wird, wird ein stdin für die Binärdatei bereitgestellt und der stdout 'on' Listener würde die Daten protokollieren. – Sai

+0

Was ist der Umfang von 'srvc'? Überschreiben Sie es bei jedem Modulanruf absichtlich? Bitte zeigen Sie uns den vollständigen Code. – Bergi

Antwort

5

Das Problem ist, dass Sie einen Prozess einmal sind Laichen und dann einen neuen data Event-Handler für jede Anforderung an Ihrem hTTP-Server hinzufügen, die nicht entfernt wird. Das würde erklären, warum die Speicherbelegung auch nach GC nicht abfällt.

Weitere (nicht verwandten) Problem ist, dass, wenn Sie Ihr Einzelkindprozess verwenden, um mehrere eingehende Anfragen zu bearbeiten, die Sie in das Problem der Mischantworten für unterschiedliche Anforderungen ausgeführt werden können (man kann nicht davon ausgehen, dass ein data Ereignis nur enthalten die Daten für eine bestimmte Anfrage). Wenn der untergeordnete Prozess node.js-basiert ist, können Sie einen ipc-Kanal damit einrichten und dann reguläre JavaScript-Werte einfach hin und her senden, anstatt stdout handling/parsing einzurichten. Wenn der untergeordnete Knoten nicht auf node.js basiert oder eine alternative (no-ipc) -Lösung benötigt, können Sie eine Warteschlange einrichten, auf die alle Anforderungen übertragen werden, und dann eine Funktion haben, die die Warteschlange verarbeitet und seriell auf jede Anforderung reagiert (erst wenn Sie irgendwie festgestellt haben, dass Sie die gesamte Ausgabe des untergeordneten Prozesses für die aktuelle Anfrage erhalten haben).

Wenn Sie stattdessen für den untergeordneten Prozess nur für eine einzelne Anfrage verwendet werden möchten, müssen Sie stattdessen Ihren Code zwicken, um pro Anfrage einmal zu spawnen (Verschieben spawn() innerhalb get()).

+0

Ich versuchte die genaue Lösung, die Sie vorschlugen, aber die Unterseite von ihm ist, wenn ich den Prozess für jede Anfrage spawn dann würde ich enden, die binäre Akte (C++ APP) für jede einzelne Anfrage laufen zu lassen, in diesem speziellen Fall ich handle 100's der Anfrage so laichen, dass viele Anzahl von Prozess wäre sehr teuer. – Sai

+1

Deshalb gab ich mehrere Lösungen für dieses sekundäre Problem (einschließlich: ipc und/oder eine Warteschlange verwenden). – mscdex

+0

in diesem Anwendungsfall habe ich mit Event-Streams zu tun, wenn eine Anfrage gemacht wird, dh wenn eine stdin an den Child-Prozess gesendet wird dann würde der Prozess kontinuierlich Daten (stdouts) ausgeben, was bedeutet, dass ich keine Queue-Logik haben kann mache nachfolgende Anfragen, sobald die aktuelle Anfrage gemacht wurde. Ich meine, ich mache eine Anfrage und das wird aktiv sein und dann sollte die App jede Anzahl von aktiven Anfragen erlauben. – Sai

Verwandte Themen