2017-06-29 26 views
20

Tôi đang tìm cách đa nền tảng để theo dõi đáng tin cậy mức tiêu thụ bộ nhớ tối đa trong quy trình Node.js, bất kể có rò rỉ hay không.Theo dõi mức tiêu thụ bộ nhớ tối đa trong quy trình Node.js

Các quy trình trong trường hợp của tôi là cả ứng dụng thực và thử nghiệm tổng hợp.

Tôi mong chờ nó làm việc như

process.on('exit',() => { 
    console.log('Max memory consumption: ' + ...); 
}); 

Đó là khả năng để theo dõi mức tiêu thụ bộ nhớ bằng cách nào đó với node --trace_gc ..., nhưng điều này dẫn đến sản lượng đó là khó đọc (và có lẽ khó có thể phân tích theo chương trình). Ngoài ra, GC không xảy ra khi tập lệnh kết thúc quá nhanh, ngay cả khi sử dụng RAM là đáng kể.

Từ những gì tôi đã thấy về đề tài này, thường memwatch là gợi ý cho rằng, giống như:

require('memwatch-next').on('stats', stats => { 
    console.log('Max memory consumption: ' + stats.max); 
}); 

Nhưng trong trường hợp của tôi nó chỉ kích hoạt khi GC đã xảy ra hoặc không kích hoạt ở tất cả, vì vậy nó là vô ích khi xác định mức tiêu thụ RAM.

Tôi muốn tránh các công cụ GUI như node-inspector nếu có thể.

Mức tiêu thụ bộ nhớ tối đa này có thể được truy xuất một cách đáng tin cậy dưới dạng số từ bản thân ứng dụng hoặc CLI, đa nền tảng không?

+0

Giải pháp của tôi có phải là crossplatform khi bạn cần nó không? – EMX

+0

@EMX Thực ra, vâng, cảm ơn, có vẻ như tôi cần. pidusage có vẻ là crossplatform. Tôi sẽ thử. – estus

+0

Tuyệt vời, hy vọng nó giải quyết câu hỏi của bạn theo cách bạn cần :) – EMX

Trả lời

8

Bạn có thể sử dụng phương pháp Node.js process.memoryUsage() để có được sử dụng bộ nhớ stat:

Các process.memoryUsage() phương thức trả về một đối tượng mô tả việc sử dụng bộ nhớ của quá trình Node.js đo bằng byte.

Nó trả về đối tượng của định dạng sau:

{ 
    rss: 4935680,  // Resident Set Size 
    heapTotal: 1826816, // Total Size of the Heap 
    heapUsed: 650472, // Heap actually Used 
    external: 49879  // memory usage of C++ objects bound to JavaScript objects managed by V8 
} 

Để có được mức tiêu thụ bộ nhớ tối đa trong quá trình Node.js, phương pháp process.nextTick có thể được sử dụng. Phương pháp process.nextTick() thêm gọi lại vào hàng đợi đánh dấu tiếp theo tiếp theo. Khi lần lượt của vòng lặp sự kiện lần lượt chạy đến khi hoàn thành, tất cả các cuộc gọi lại hiện tại trong hàng đợi đánh dấu tiếp theo sẽ được gọi.

let _maxMemoryConsumption; 
let _dtOfMaxMemoryConsumption; 

process.nextTick(() => { 
    let memUsage = process.memoryUsage(); 
    if (memUsage.rss > _maxMemoryConsumption) { 
    _maxMemoryConsumption = memUsage.rss; 
    _dtOfMaxMemoryConsumption = new Date(); 
    } 
}); 

process.on('exit',() => { 
    console.log(`Max memory consumption: ${_maxMemoryConsumption} at ${_dtOfMaxMemoryConsumption}`); 
}); 
+0

Cảm ơn, nó hoạt động. Có lỗi chính tả trong các tên biến. Ngoài ra, nó có khả năng sẽ chạy trên cùng một đánh dấu và trên lối ra cũng như để có được bảo hiểm đầy đủ. – estus

+0

@estus Tôi đã sửa tên biến, cảm ơn vì đã đề cập đến điều này. Điều gì về việc thêm tính toán trong gọi lại 'thoát', tôi không nghĩ rằng nó là cần thiết (tất nhiên nếu bạn không muốn tạo một đối tượng khổng lồ ở đó :)). Sự kiện này thường được sử dụng để nhớ _cleanup_. – alexmac

+0

Có, thêm phép tính để thoát * ngoài nextTick * hoạt động khá tốt. Nhưng vấn đề tôi gặp phải là process.nextTick nên được thiết lập đệ quy để theo dõi nó trong các tập lệnh async, nhưng thực tế là có khoảng thời gian không đầy đủ ngăn không cho nó gọi 'exit' khi kịch bản kết thúc. Tôi đã giải nó bằng 'setInterval (tính, 10) .unref(); process.on ('thoát', tính toán); process.on ('thoát',() => {...}) '. – estus

4

Nếu bạn cố gắng đánh giá quá trình từ bên trong chính nó, bạn sẽ bị bóp méo giá trị sử dụng bộ nhớ. (Nếu bạn muốn biết thêm thông tin về vấn đề này, chỉ cần bình luận)


Đây là một chút (crossplatform) công cụ tôi mã để kiểm tra việc sử dụng bộ nhớ của tiến trình khác, chúng đẻ trứng trong một quá trình độc lập và đồng hồ mỗi 100ms cho sử dụng bộ nhớ để tìm ra đỉnh cao nhất, đầu ra mỗi khi một đỉnh mới được tìm thấy và dừng lại khi trẻ đã kết thúc.

Nó sử dụng pidusage mà là một quá trình crossplatform (cpu% và) bộ nhớ sử dụng một PID

Cho phép tuỳ biến của các spawn (đối số được chuyển cùng với spawn) [có thể được cập nhật cho lệnh sử dụng đường dây]

Nó cũng sẽ hoạt động với bất kỳ tên nhị phân nút nào vì nó sẽ sử dụng lại tên được sử dụng để khởi động công cụ này.

'use strict' 
const UI = {}; var ñ = " " 
const pusage = require('pidusage'); 
//:Setup the 'cmd' array to be the file and arguments to be used 
const ANALYSIS = {cmd:['child.js']} 
ANALYSIS.child = require('child_process').spawn(
process.argv[0], // reuse to work with the same binary name used to run this (node|nodejs|...) 
ANALYSIS.cmd, // array with filePath & arguments to spawn for this analisis 
{ //So the child_process doesn't behave like a child 
    detached:true,  
    stdio:['ignore'], 
    env:null 
} 
); 
//:The Analysis 
DoAnalysis(ANALYSIS.child.pid); 
ANALYSIS.child.unref() 
var memPeak = 0; 
function PIDStat(){ 
pusage.stat(ANALYSIS.pid, function(err, stat) { 
    if(err){ CheckError(err) }else{ 
    if(stat.memory > memPeak){memPeak=stat.memory;PrintStat()} 
    setTimeout(PIDStat,100); pusage.unmonitor(process.pid) 
    } 
}) 
} 
//:UI (just for display) 
function DoAnalysis(PID){ 
var s = '═'.repeat(ANALYSIS.cmd[0].toString().length) 
ANALYSIS.pid = PID; 
UI.top = '╒═'+s+'═╕' 
UI.mid = '│ '+ANALYSIS.cmd[0]+' │' 
UI.bot = '╘═'+s+'═╛' 
console.log(UI.x); 
PIDStat() 
} 
function PrintStat(){ 
console.clear() 
console.log('\n',UI.top,'\n',UI.mid,'PEAK MEM. :',memPeak,'\n',UI.bot) 
} 
function CheckError(e){ 
switch(e.code){ 
    case "ENOENT": console.log("    [the analysis ended]\n"); break; 
    default: console.log("[/!\\ error]\n",e); break 
} 
} 

sẽ cho kết quả sau:

╒══════════╕ 
│ child.js │ PEAK MEM. : 28737536 
╘══════════╛ 
       [the analysis ended] 

Công cụ này ngăn không cho bạn thêm sưng lên để làm mã của quá trình bạn thực sự muốn chuẩn, vì vậy cách này bạn sẽ không có được giá trị sử dụng bộ nhớ khác nhau, vì mã bloat/điểm chuẩn của bạn cũng sẽ thêm mức sử dụng bộ nhớ vào quá trình đó.

+0

Đoạn mã trên không thành công trên console.clear() trong Node 6, nó gần đây đã được thêm vào API Node. Cảm ơn, nó hoạt động như dự định. Nó nên được đề cập rằng nó không hoạt động tốt trên các quá trình chạy đồng bộ, kịch bản có thể bỏ lỡ điểm mà chúng có đỉnh. Đối với các đối số bloating, tôi thấy rằng process.memoryUsage() chạy trên mỗi đánh dấu và được đề xuất trong câu trả lời khác cung cấp không ảnh hưởng đến CPU và RAM, do đó, nó không phải là một việc lớn. – estus

+0

@estus Làm thế nào một cuộc gọi có tác động ** không ** lên CPU? :) – bluehipy

+0

@ bluehipy Nó không đáng kể, không đúng nghĩa là 0. Tôi đã sửa chữa, 'process.memoryUsage()' đã cho 2-3% khi theo dõi trên mỗi tick và ~ 0% khi theo dõi với khoảng 10ms (hoàn toàn có thể chấp nhận được trong một tình huống như thế) – estus

Các vấn đề liên quan