Get process CPU usage in percentage
Asked Answered
N

4

14

The process.cpuUsage() function displays some weird microsecond values. How to get cpu usage in percentage?

Negotiate answered 6/8, 2020 at 18:46 Comment(4)
Does this answer your question? Get/View Memory & CPU usage via NodeJSHysterics
Take a look here: gist.github.com/bag-man/5570809Baring
tx Treast, I tried it but it shows me the global CPU usage. I want to get % CPU used by the current process onlyNegotiate
Try this: npmjs.com/package/pidusageJonahjonas
H
10

You can achieve this using the additional os native module to get informations about your CPUs:

const os = require('os');

// Take the first CPU, considering every CPUs have the same specs
// and every NodeJS process only uses one at a time.
const cpus = os.cpus();
const cpu = cpus[0];

// Accumulate every CPU times values
const total = Object.values(cpu.times).reduce(
    (acc, tv) => acc + tv, 0
);

// Normalize the one returned by process.cpuUsage() 
// (microseconds VS miliseconds)
const usage = process.cpuUsage();
const currentCPUUsage = (usage.user + usage.system) * 1000;

// Find out the percentage used for this specific CPU
const perc = currentCPUUsage / total * 100;

console.log(`CPU Usage (%): ${perc}`);

If you want to get the global CPU usage (taking all your CPUs into account), you need to accumulate every times of every CPUs, not only the first one, but that should be less useful in most cases.

Note that only the "system" time can use more than the first CPU because the calls can run in other threads separated from the NodeJS core.

Sources :

Hypothermia answered 10/8, 2020 at 15:26 Comment(5)
CPU Usage (%): 2277.5823913285444 CPU Usage (%): 2343.7592809543803 CPU Usage (%): 2510.3689922995127 Does not seem to get percentage properly on windowsRolon
const currentCPUUsage = (usage.user + usage.system) / 1000; must divide by 1000 not multiplyBridge
Seems to be different between oses, watch it outHypothermia
is this only for a single core or is it for the whole CPU?Concealment
The example is only for the usage of first CPU (note the comment below the code), you can iterate and compute an average for all the CPUs if neededHypothermia
C
6

An alternative, assuming you are running node under linux/macos O.S. is:

var exec = require("child_process").exec;

function getProcessPercent() {

  // GET current node process id.
  const pid = process.pid;
  console.log(pid);

  //linux command to get cpu percentage for the specific Process Id.
  var cmd = `ps up "${pid}" | tail -n1 | tr -s ' ' | cut -f3 -d' '`;

  setInterval(() => {
    //executes the command and returns the percentage value
    exec(cmd, function (err, percentValue) {
      if (err) {
        console.log("Command `ps` returned an error!");
      } else {
        console.log(`${percentValue* 1}%`);
      }
    });
  }, 1000);
}

getProcessPercent();

If your O.S is windows, your command must be different. As i'm not running windows i can't tell to you the exact command, but you can start from here:

tasklist

get-process

WMIC

You can also check the platform with process.platform and do an if/else statment setting the right command for the specific OS.

Camilla answered 10/8, 2020 at 17:41 Comment(0)
G
4

Before answering we need to take care about a couple of facts:

  • Node.js does not uses only one CPU, but every async I/O operation may use additional CPUs
  • the times returned by process.cpuUsage are cumulative of all CPUs used by the Node.js process

so to calculate the CPU usage of Node.js considering all the CPUs of the host, we could use something similar to:

const ncpu = require("os").cpus().length;
let previousTime = new Date().getTime();
let previousUsage = process.cpuUsage();
let lastUsage;

setInterval(() => {
    const currentUsage = process.cpuUsage(previousUsage);

    previousUsage = process.cpuUsage();

    // we can't do simply times / 10000 / ncpu because we can't trust
    // setInterval is executed exactly every 1.000.000 microseconds
    const currentTime = new Date().getTime();
    // times from process.cpuUsage are in microseconds while delta time in milliseconds
    // * 10 to have the value in percentage for only one cpu
    // * ncpu to have the percentage for all cpus af the host

    // this should match top's %CPU
    const timeDelta = (currentTime - previousTime) * 10;
    // this would take care of CPUs number of the host
    // const timeDelta = (currentTime - previousTime) * 10 * ncpu;
    const { user, system } = currentUsage;

    lastUsage = { system: system / timeDelta, total: (system + user) / timeDelta, user: user / timeDelta };
    previousTime = currentTime;

    console.log(lastUsage);
}, 1000);

or we can read the value of lastUsage from where we need it rather printing it to the console.

Gravimeter answered 9/8, 2020 at 20:53 Comment(2)
I don't think this works right. Every 2nd call the cpu is higher even when idle. Plus the values don't match the ones from topNegotiate
You are right @Negotiate ; now I should have fix it. Please take in account that top's %CPU is against a single CPU, if the process uses more than a single CPU the value can increase higher than 100%Gravimeter
T
3

Try using the below code to get cpu usage in %

var startTime  = process.hrtime()
var startUsage = process.cpuUsage()

// spin the CPU for 500 milliseconds
var now = Date.now()
while (Date.now() - now < 500)

var elapTime = process.hrtime(startTime)
var elapUsage = process.cpuUsage(startUsage)

var elapTimeMS = secNSec2ms(elapTime)
var elapUserMS = secNSec2ms(elapUsage.user)
var elapSystMS = secNSec2ms(elapUsage.system)
var cpuPercent = Math.round(100 * (elapUserMS + elapSystMS) / elapTimeMS)

console.log('elapsed time ms:  ', elapTimeMS)
console.log('elapsed user ms:  ', elapUserMS)
console.log('elapsed system ms:', elapSystMS)
console.log('cpu percent:      ', cpuPercent)

function secNSec2ms (secNSec) {
  return secNSec[0] * 1000 + secNSec[1] / 1000000
}

try tweaking the secNSec2ms function to the following to check if it solves your problem.

function secNSec2ms(secNSec) {
  if (Array.isArray(secNSec))
  return secNSec[0] * 1000 + secNSec[1] / 1000000 return secNSec / 1000;
}
Tedda answered 14/8, 2020 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.