Surveiller la consommation maximale de mémoire dans le noeud.processus js

je suis à la recherche d'un moyen multiplateformes pour surveiller de façon fiable la consommation maximale de mémoire dans le noeud.processus js, qu'il y ait ou non des fuites.

les processus dans mon cas sont à la fois des applications réelles et des tests synthétiques.

je m'attends à ce qu'il fonctionne comme

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

il était possible de retracer la consommation de mémoire d'une façon ou d'une autre avec node --trace_gc ..., mais cela a abouti à une sortie qui est difficile à lire (et probablement difficile à analyser programmatiquement). Également, GC ne se produisait pas quand un script finissait trop vite, même si L'utilisation de la RAM était importante.

De ce que j'ai vu sur le sujet, généralement memwatch est suggéré pour que, comme:

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

mais dans mon cas, il n'a été déclenché que lorsque GC s'est déjà produit ou ne s'est pas déclenché du tout, donc il était inutile pour déterminer les pics de consommation de RAM.

je préfère éviter d'outils graphiques comme node-inspector si possible.

cette consommation maximale de mémoire peut-elle être fiable? extrait en tant que numéro de l'application elle-même ou CLI seul, cross-plate-forme?

20
demandé sur estus 2017-06-29 18:29:47

2 réponses

vous pourriez utiliser le noeud.js process.memoryUsage() méthode pour obtenir l'utilisation de la mémoire stat:

Le processus.la méthode memoryUsage () renvoie un objet décrivant l'utilisation de la mémoire du noeud.processus js mesuré en octets.

Il renvoie l'objet du format suivant:

{
  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
}

pour obtenir la consommation de mémoire maximale dans le noeud.processus js,process.nextTick méthode pourrait être utilisée. process.nextTick() la méthode ajoute le rappel au suivant cochez la file d'attente. Une fois l' tour actuel de la boucle d'événement le tour s'exécute jusqu'à son achèvement, toutes les callbacks actuellement dans la prochaine file d'attente seront appelées.

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}`);
});
9
répondu alexmac 2017-08-31 13:51:18

si vous essayez de comparer le processus de l'intérieur de lui-même, vous aurez déformé les valeurs d'utilisation de la mémoire. (si vous voulez plus d'informations à ce sujet, juste un commentaire)


C'est un peu (compatible) outil que j'ai codé pour vérifier l'utilisation de la mémoire d'un autre processus, il produit un processus indépendant et regarde tous les 100ms pour l'utilisation de la mémoire afin de trouver le pic le plus élevé, les sorties chaque fois qu'un nouveau pic est trouvé et s'arrête une fois que l'enfant a terminer.

pidusage qui est un processus crossplatform (cpu % et)mémoire utilisation d'un PID

Permet la personnalisation du spawn (les arguments passés avec le spawn) [pourrait être mis à jour pour l'utilisation de lignes de commande]

il fonctionnera aussi avec n'importe quel nom binaire de noeud, puisqu'il réutilisera celui utilisé pour démarrer cet outil.

'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
 }
}

produira la sortie suivante :

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

cet outil vous empêche d'ajouter du bloat au code du processus que vous voulez réellement comparer, de cette façon vous n'obtiendrez pas différentes valeurs d'utilisation de la mémoire, puisque votre code de bloat/benchmarking ajoutera également l'utilisation de la mémoire à ce processus.

4
répondu EMX 2017-08-27 16:55:59