2013-10-23 6 views
6

Vermeintliche ich einen einfachen HTTP-Server habe, wie:Speicherverlust bei Verwendung von Streams in Node.js?

var http = require('http'); 

http.createServer(function (req, res) { 
    req.on('data', function (data) { 
    console.log('Got some data: ' + data); 
    }); 

    req.on('end', function() { 
    console.log('Request ended!'); 
    }); 

    res.end('Hello world!'); 
}).listen(3000); 

Also, im Grunde die Standard-101 Probe, nichts Besonderes bisher - außer, dass ich auf die data und dem end Ereignis der lesbaren req Stream abonnieren. Jetzt frage ich mich, ob ich diese Ereignisse abbestellen muss, wenn ich sie nicht mehr brauche?

Oder werden sie automatisch gelöscht, wenn der lesbare Stream endet?

Könnte Code wie dieser Speicherverlust verursachen?

+3

[Dies] (http://stackoverflow.com/questions/5326300/garbage-collection-with-node-js) könnte hilfreich sein. – hexacyanide

+0

Das war eigentlich in einem gesunden Menschenverstand hilfreich. Danke :-) –

Antwort

15

(Diese Antwort enthält Links zu den Revelant Teile des node.js Quellcode)

Bevor Sie Ihre Frage zu beantworten, lassen Sie uns über die Ereignisse sprechen. Wenn Sie dies tun:

emitter.on('an-event', listener); 

listener wird auf eine zu emitter angebracht list hinzugefügt. Später, wenn emitter das Ereignis auslöst, benachrichtigt es alle Listener, die das Ereignis abonniert haben, indem es die Liste durchläuft. Die Magie der Ereignisemitter node.js besteht darin, dass Sie diese Liste nicht selbst deklarieren oder verwalten.

Wenn Sie jedoch .on() anrufen, erstellen Sie einen back-reference Emitter -> Listener. Diese Referenz verhindert, dass der Listener vom GC erfasst wird, und erstellt ein "Leak", wenn Sie sich nie abmelden.

Dies passiert nicht sehr oft mit node.js, weil Emitter normalerweise vor Listenern zerstört werden, aber ein echter Fall ist, wenn Sie eine lange Verbindung haben (denken Sie Twitter Streaming API), die manchmal wieder verbindet . Wenn Sie die Registrierung von Ereignissen nicht aufheben, erhalten Sie möglicherweise Ereignisse von der alten Verbindung und denken, dass sie auf die neue Verbindung zutreffen. Dies kann dazu führen, dass Sie denken, dass die neue Verbindung geschlossen wurde.

node.js wird die berüchtigte Nachricht "possible leak detected" ausdrucken, wenn sie denkt, dass Sie vergessen haben, Listener abzumelden.

Zurück zu Ihrem Beispiel:

Dies wird nicht ein Leck verursachen, weil die Buchse (erf + res) zuerst zerstört werden. Da es der Emitter ist, wird node.js forcibly remove all listeners.

+0

Ausgezeichnete Antwort, vielen Dank, vor allem für den Teil mit, wenn Emitter zerstört werden. :-) –

Verwandte Themen