2014-11-26 13 views
5

Tôi vừa hoàn thành phát triển ứng dụng node.js đầu tiên và bây giờ tôi đang thử nghiệm trên VPS của mình. quan sát việc sử dụng tài nguyên của quá trình "nút", tôi đã nhận thấy sự gia tăng sử dụng bộ nhớ khi một trang (đặc biệt là một số) được yêu cầu. Đặc biệt, nếu trang được yêu cầu là một trang tĩnh, mức tăng là tối thiểu. Nếu trang được yêu cầu là/admin, mức tăng có thể là 1mb! Tất nhiên, khi/admin được yêu cầu, máy chủ của tôi làm nhiều việc hơn là phục vụ một trang tĩnh. Ông kết nối với mongodb, ông thực hiện 4 "tìm", ông liên kết các kết quả với một mẫu html sử dụng bind. Bây giờ, vấn đề là gì? Bộ nhớ này được sử dụng, sẽ không bao giờ được phát hành !!! Vì vậy, tôi nghĩ rằng có một lỗi logic trong mã của tôi nhưng sau đó tôi đã làm một thử nghiệm thú vị hơn nhiều.Bộ nhớ đã sử dụng không bao giờ được giải phóng trong nút js. Rất lạ

Xem xét việc này nodejs máy chủ rất đơn giản:

var http = require('http'); 
http.createServer(function (req, res) { 
    res.writeHead(200, {'Content-Type': 'text/plain'}); 
    res.end('Hello World\n'); 
}).listen(3000, 'my_public_ip'); 

nếu tôi cố gắng tạo nhiều yêu cầu với trình duyệt (chỉ đơn giản bằng cách giữ f5 trong một phút), sử dụng bộ nhớ phát triển chậm và bộ nhớ sử dụng bởi quá trình này sẽ không bao giờ được phát hành, thậm chí sau một thời gian dài và sau khi đóng trình duyệt. Bây giờ, có thể có một số lỗi (1mb bộ nhớ được sử dụng và không bao giờ được phát hành cho mỗi yêu cầu nó rất cao!), Nhưng tôi nghĩ rằng nó rất lạ mà bộ nhớ được sử dụng bởi tập lệnh đơn giản ở trên sẽ không bao giờ được phát hành ! Bạn nghĩ gì về điều này? Có cách nào để tránh nó?

Ngoài ra, (trong máy chủ thật của tôi), tôi sử dụng memwatch trong Thys cách:

var memwatch = require('memwatch'); 
    memwatch.on('leak', function(info) { 
     console.log(info); 
     process.exit(1); 
    }); 

Nếu tôi thực hiện nhiều yêu cầu với trình duyệt, sau khoảng 10 giây mà tôi đang làm nó, quá trình này sẽ thoát và đây là lỗi:

{ start: Wed Nov 26 2014 08:21:07 GMT-0500 (EST), 
    end: Wed Nov 26 2014 08:22:04 GMT-0500 (EST), 
    growth: 4775624, 
    reason: 'heap growth over 5 consecutive GCs (57s) - 287.65 mb/hr' } 

Có nghĩa là gì ?? Có vẻ như có liên quan với bộ thu gom rác! Tôi biết rằng sẽ tốt hơn nếu dán mã/admin của tôi ở đây nhưng đoạn mã rất dài và có liên quan đến các biến toàn cầu, vì vậy không thể hiểu được nếu không có bản sao của 200 dòng: D. Nếu bạn cần thêm thông tin tôi sẽ cung cấp cho bạn!

+1

Bạn đã cố gắng ép buộc thu gom rác theo cách thủ công chưa? Kiểm tra http://devjar.me/post/22886448979/manually-run-gc-in-node-js: "Bắt đầu Nút bằng cờ —nouse_idle_notification và —expose_gc, và sau đó khi bạn muốn chạy GC, chỉ cần gọi toàn cầu .gc(). " – Joel

+0

Bạn có thể đăng mã bằng gist/pastebin. Nhưng thực tế đơn giản là bạn đang đề cập đến các vars toàn cầu sẽ kích hoạt cảnh báo :) Chúng tôi cần thêm thông tin. Ngoài ra, hãy thử để 'memwatch' mã nóng, không phải ngay sau khi khởi động. – randunel

+0

I (Andras) đã thử đoạn mã trên với gc cưỡng bức, và nó rất rất dần dần, nhưng một cái gì đó đang diễn ra. Hơn 200 giây và 580.000 cuộc gọi heapSử dụng tăng 40KB (bit nhỏ), nhưng heapTotal tăng 12MB, đầu tiên là +4 rồi +8. Tôi đang chạy 5 phút chạy ngay bây giờ – Andras

Trả lời

5

Nút không đáng ngạc nhiên không giải phóng bộ nhớ, hầu hết các chương trình đều không. Họ tham lam: nếu họ chạy ngắn, họ nhận được nhiều bộ nhớ hơn từ hệ thống. Nếu họ có thêm, họ giữ nó để có cho sau này.

Máy chủ mẫu ngắn không bị rò rỉ bộ nhớ. Tôi đã chạy thử nghiệm 14 phút với nút v0.10.29; sử dụng bộ nhớ chỉ phát triển chậm ban đầu, sau đó nó dừng lại. Tốc độ tăng trưởng ít hơn một bit cho mỗi cuộc gọi http, do đó, nó không thể tự rò rỉ bộ nhớ trong các cuộc gọi. Nó có thể là có thể phân mảnh bộ nhớ gây ra bởi thời gian chạy nodejs có thể dẫn đến tăng trưởng heap cho đến khi có đủ bộ nhớ rảnh rỗi để bù đắp cho sự phân mảnh.

Sau 14 phút, quá trình nodejs vẫn chỉ sử dụng 2MB trong tổng số 21MB, như khi nó bắt đầu. (14 vì thời gian chạy 15 phút bị tạm dừng cho 1:09)

Đây là mức tăng trưởng hơn 2,46 triệu cuộc gọi http (chỉ hiển thị thay đổi heapTotal và cuối cùng. Dấu chân bộ nhớ cuối cùng đạt được sau 4 phút và không thay đổi trong 11 phút tiếp theo):

2014-12-03T04: 52: 48.358Z {rss: 12.222.464, heapTotal: 7.130.752, heapUsed: 1.751.228}
2014-12-03T04: 52: 55.182Z {rss: 17.326.080 , heapTotal: 9227904, heapĐược sử dụng: 2186528}
2014-12-03T04: 53: 59.488Z {rss: 21172224, heapTổng số: 13422208, heapSử dụng: 2092796}
2014-12-03T04: 56: 58.897Z {rss: 29556736 , heapTổng số: 21810816, heapSử dụng: 2100000 }
(...được dừng lại 01:09 xung quanh 05:02:27)
2014-12-03T05: 07: 45.598Z {rss: 29.446.144, heapTotal: 21.810.816, heapUsed: 2.138.608}

của tôi (sửa đổi đôi chút) kiểm tra:

var ncalls = 0; 
var http = require('http'); 
http.createServer(function (req, res) { 
    res.writeHead(200, {'Content-Type': 'text/plain'}); 
    res.end('Hello World\n'); 
    if (ncalls++ % 100000 === 0) { 
    global.gc(); 
    console.log(new Date().toISOString(), process.memoryUsage()); 
    } 
}).listen(3000, '127.0.0.1'); 
console.log("Listening on 3000..."); 
Các vấn đề liên quan