2013-04-18 30 views
10

v0.10.4nodejs setTimeout bellek sızıntısı?

İşte giderek artan bellek kullanımı ile sonuçlanan basit döngü var: Neyi yanlış yapıyorum

function redx(){ 
     setTimeout(function(){ redx() },1000); 
     console.log('loop'); 
} 

redx(); 

??

DÜZENLEME

Tamam, sakin kapsamında aşımı nesnesine başvurmak için öneri çalıştı ve çöp toplama TOP dan yaklaşık 40 saniye sonra burada kısaltılmış oluyor günlükleri tekme olmadığını görünüyor:

3941 kök 20 0 32944 7284 4084 S 4,587 3.406 0: 01.32 düğüm
3941 kök 20 0 32944 7460 4084 G 2.948 3.489 0: 01,59 düğüm
3941 kök 20 0 32944 7516 4084 G 2.948 3,515 0: 01,68 düğüm
3941 kök 20 0 33.968 8400 4112 S 2.948 3.928 0: 02.15 düğüm
3941 kök 20 0 33968 8920 4112 G 3.275 4.171 0: 02,98 düğüm
3941 kök 20 0 33968 8964 4112 G 2.948 4.192 0: 03.07 düğüm
3941 kök 20 0 33968 9212 4112 G 2.953 4.308 0: 03.16 düğüm
3941 kök 20 0 33968 9212 4112 G 2.953 4.308 0: 03,25 düğüm
3941 kök 20 0 33968 9212 4112 G 3.276 4.308 0: 03,35 düğüm
3941 kök 20 0 33968 9212 4112 G 2.950 4.308 0: 03,44 düğüm

+0

İnanılmaz, Dün kendimi merak ediyordum. Tahminimce Düğüm, anonim işlevlerin kapanışlarını toplamaz. – dualed

+0

Hangi işletim sistemi üzerinde çalışıyorsunuz? – dualed

+0

Bunu ARCH kapsamında test ediyorum. – crankshaft

cevap

4

Resim fikri niçin ancak zaman aşımı nesnesine başvuruda bulunuyorsanız nodejs işlevini göz önünde bulundurarak çöpleri doğru şekilde toplayacaktır.

function redx(){ 
     var t = setTimeout(function(){ redx() },50); 
     console.log('hi'); 
} 

redx(); 
+0

Teşekkürler, sadece kodunuzu test ettim ve maalesef bu sorunu çözmüyor ve bellek tüketiminde gözle görülür bir fark görmüyorum. – crankshaft

+0

Düzeltme, Sadece buna tekrar baktım ve bellek kullanımı başlangıçta artarak devam ediyor ve sonra yaklaşık 40 saniye sonra doruğa çıkıyor! – crankshaft

+0

garip, ben açıkça bellek kullanımı artar ve daha sonra başlangıç ​​değerine geri dönme (gc başladığı zaman sanırım) –

3

Aslında, V8 çöp toplayıcısının çalışmasının yolu olabileceğini düşünüyorum.

Sistemimde, düğüm yığınının 48 MB'ye kadar yükselme ve ardından kararlı hale getirme eğilimi vardır; bu nedenle, programınızı uzun süre çalışır durumda tutarsanız, bellek tüketiminin sonunda dengeleneceğini düşünüyorum.

Düğümün V8 komut satırı seçeneklerinden birini kullanarak başlatarak GC'nin ne zaman/nasıl başlatılacağı hakkında bilgi alabilirsiniz: --trace_gc bayrağı.

Redis ile ilk denemelerinizde, her çağrıda sistemli olarak Redis'ten bağlanıyorsunuz. Bu çöp üretme eğilimindedir. Bir kez bir bağlantı açmanız ve birçok kez kullanmanız gerekiyor. Yine de, bunu yaptığımda bile, bellek tüketimi dengelenmeye eğilimlidir. İşte REDIS ile bu örnekte bellek tüketimi evrimdir: Burada

// something close to your initial function (when Redis was still in the picture) 
function redx(){ 
    var client = redis.createClient(); 
    client.get("tally", function(err, reply) { 
     client.quit(); 
    }); 
    setTimeout(function(){ redx() }, 50); 
} 

Evolution of memory consumption with Redis connect/disconnect

, 60 MB sonra stabilizasyon oldukça açık görünüyor.

+0

Teşekkürler, evet originaly Bunun redis/memcache ile ilgili bir sorun olduğunu düşündüm ama kodu en az bir düzeye çıkardıktan sonra, yalnızca setTimeout'un bu sızıntıya neden olduğunu buldum. Yeni bir bağlantı açmaya devam ettiğim için, bu aylarca sürebilir ve bu süre için bir localhost bağlantısı açık tutmanın güvenilir olup olmayacağından emin değildim. – crankshaft

+0

Yukarıdaki grafiği onaylayabilirim. Nodejs bir süre sonra hafıza tüketimini stabilize ediyor gibi görünüyor. Bu çoğu GC'de tipiktir. Hatta setTimeout döngüsünde redx() işlevini çağıran izole bir alan oluşturarak da aynı sonuçları elde ettim. Ben de setTimeout (redx.bind (null), 50); Yukarıdaki örnekte bir tahminim var, 'var client = ... 'bir sonraki döngüden sonra ulaşılamıyor, böylece bir süre sonra toplanan Çöpleri alır ve böylece bellek sızıntısı da uygulanmamalıdır. Mem Leak'i Redis'e üretebilir, ancak bu tartışma dışıdır. –