2013-04-18 30 views
10

v0.10.4nodejs setTimeout memory leak?

Đây là vòng lặp đơn giản mà kết quả trong một sử dụng bộ nhớ ngày càng tăng:

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

redx(); 

Tôi đang làm gì vậy ??

EDIT

OK, chỉ cần cố gắng gợi ý để tham khảo các đối tượng thời gian chờ trong phạm vi và có vẻ như thu gom rác thải không kick vào sau khoảng 40 giây, các bản ghi đây là viết tắt từ TOP:

3941 gốc 20 0 32944 7284 4084 S 4,587 3,406 0: 01,32 nút
3941 gốc 20 0 32944 7460 4084 S 2,948 3,489 0: 01,59 nút
3941 gốc 20 0 32944 7516 4084 S 2,948 3,515 0: 01,68 nút
3941 gốc 20 0 33.968 8400 4112 S 2.948 3.928 0: 02.15 nút
3941 gốc 20 0 33968 8920 4112 S 3,275 4,171 0: 02,98 nút
3941 gốc 20 0 33968 8964 4112 S 2,948 4,192 0: 03.07 nút
3941 gốc 20 0 33968 9212 4112 S 2,953 4,308 0: 03,16 nút
3941 gốc 20 0 33968 9212 4112 S 2,953 4,308 0: 03,25 nút
3941 gốc 20 0 33968 9212 4112 S 3,276 4,308 0: 03,35 nút
3941 gốc 20 0 33968 9212 4112 S 2,950 4,308 0: 03,44 nút

+0

Đáng kinh ngạc, tôi đã tự hỏi bản thân mình hôm qua. Tôi đoán là Node không thu thập các đóng của hàm ẩn danh. – dualed

+0

Bạn đang làm việc với hệ điều hành nào? – dualed

+0

Tôi đang thử nghiệm điều này dưới ARCH. – crankshaft

Trả lời

4

Không ý tưởng tại sao nhưng rõ ràng nếu bạn tham chiếu đến đối tượng timeout trong phạm vi của các nút chức năng sẽ làm việc thu thập rác một cách chính xác.

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

redx(); 
+0

Cảm ơn, tôi vừa thử nghiệm mã của bạn và không may cho tôi, nó không giải quyết được vấn đề và tôi không thấy có sự khác biệt đáng chú ý nào trong mức tiêu thụ bộ nhớ. – crankshaft

+0

Chỉnh sửa, tôi chỉ xem xét lại việc sử dụng bộ nhớ này và tiếp tục tăng ban đầu và sau đó đạt mức cao nhất sau khoảng 40 giây! – crankshaft

+0

lạ, tôi có thể thấy rõ việc sử dụng bộ nhớ tăng lên và sau đó quay trở lại giá trị ban đầu (tôi đoán điều đó khi gc đá vào) –

3

Thực ra, tôi nghĩ đó có thể chỉ là cách trình thu gom rác V8 hoạt động.

Trên hệ thống của tôi, heap nút có xu hướng tăng lên đến 48 MB và sau đó ổn định, vì vậy tôi nghĩ rằng nếu bạn giữ cho chương trình của bạn chạy trong một thời gian dài, tiêu thụ bộ nhớ cuối cùng sẽ ổn định.

Bạn có thể có thông tin về thời gian/cách GC khởi động bằng cách khởi chạy nút bằng một trong các tùy chọn dòng lệnh V8: cờ --trace_gc.

Trong lần thử đầu tiên với Redis, bạn đã kết nối/ngắt kết nối có hệ thống khỏi Redis tại mỗi cuộc gọi. Điều này có xu hướng tạo ra rác thải. Bạn có nghĩa vụ phải mở một kết nối một lần và sử dụng nó nhiều lần. Tuy nhiên, ngay cả khi tôi làm điều này, tiêu thụ bộ nhớ có xu hướng ổn định. Đây là sự phát triển của tiêu thụ bộ nhớ trên ví dụ này với Redis:

// 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

Ở đây, ổn định sau 60 MB có vẻ là khá rõ ràng.

+0

Cảm ơn, có bản gốc Tôi nghĩ rằng đây là một vấn đề với redis/memcache nhưng sau khi tước mã đến mức tối thiểu, tôi thấy rằng chỉ cần setTimeout là kết quả trong rò rỉ này. Lý do tôi tiếp tục mở một kết nối mới, là điều này có thể chạy trong nhiều tháng và tôi đã không chắc chắn nếu giữ mở một kết nối localhost cho rằng số lượng thời gian sẽ là đáng tin cậy. – crankshaft

+0

Tôi có thể xác nhận biểu đồ trên. Nodejs dường như ổn định mức tiêu thụ bộ nhớ của nó sau một thời gian. Điều này rất điển hình trong hầu hết các GC. Tôi thậm chí đã có kết quả tương tự bằng cách tạo ra một phạm vi cô lập được gọi là 'redx()' trong một vòng lặp setTimeout. Tôi cũng có cùng một đồ thị bằng cách gọi 'setTimeout (redx.bind (null), 50);'. Tôi có một đoán trong ví dụ trên, 'var client = ...' là nhận được unreachable sau khi vòng tiếp theo để nó được Garbage thu thập sau một thời gian, và vì vậy rò rỉ bộ nhớ cũng không nên áp dụng. nó có thể tạo ra Mem Leak to Redis nhưng đây là một cuộc thảo luận. –