Skip to content

Commit

Permalink
Fix cpu percentage formula
Browse files Browse the repository at this point in the history
  • Loading branch information
simonepri committed Jun 3, 2018
1 parent 174fe65 commit 88972d8
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 27 deletions.
9 changes: 4 additions & 5 deletions README.md
Expand Up @@ -25,7 +25,7 @@ setInterval(function () {
pidusage(process.pid, function (err, stats) {
console.log(stats)
// => {
// cpu: 10.0, // percentage (it may happen to be greater than 100%)
// cpu: 10.0, // percentage (0-100%)
// memory: 357306368, // bytes
// ppid: 312, // PPID
// pid: 727, // PID
Expand All @@ -41,7 +41,7 @@ pidusage([727, 1234], function (err, stats) {
console.log(stats)
// => {
// 727: {
// cpu: 10.0, // percentage
// cpu: 10.0, // percentage (0-100%)
// memory: 357306368, // bytes
// ppid: 312, // PPID
// pid: 727, // PID
Expand All @@ -50,7 +50,7 @@ pidusage([727, 1234], function (err, stats) {
// timestamp: 864000000 // ms since epoch
// },
// 1234: {
// cpu: 0.1, // percentage
// cpu: 0.1, // percentage (0-100%)
// memory: 3846144, // bytes
// ppid: 727, // PPID
// pid: 1234, // PID
Expand All @@ -65,7 +65,7 @@ pidusage([727, 1234], function (err, stats) {
const stats = await pidusage(process.pid)
console.log(stats)
// => {
// cpu: 10.0, // percentage (it may happen to be greater than 100%)
// cpu: 10.0, // percentage (0-100%)
// memory: 357306368, // bytes
// ppid: 312, // PPID
// pid: 727, // PID
Expand Down Expand Up @@ -135,4 +135,3 @@ This project is licensed under the MIT License - see the [LICENSE][license] file

[node:cpuUsage]: https://nodejs.org/api/process.html#process_process_cpuusage_previousvalue
[node:memUsage]: https://nodejs.org/api/process.html#process_process_memoryusage

23 changes: 11 additions & 12 deletions lib/procfile.js
Expand Up @@ -3,7 +3,7 @@ var path = require('path')
var updateCpu = require('./helpers/cpu')
var parallel = require('./helpers/parallel')
var history = require('./history')
var cpu = null
var cpuInfo = null

function readProcFile (pid, options, done) {
var hst = history.get(pid, options.maxage)
Expand All @@ -18,7 +18,7 @@ function readProcFile (pid, options, done) {
return done(err, null)
}
var date = Date.now()

// https://github.com/arunoda/node-usage/commit/a6ca74ecb8dd452c3c00ed2bde93294d7bb75aa8
// preventing process space in name by removing values before last ) (pid (name) ...)
var index = infos.lastIndexOf(')')
Expand All @@ -32,29 +32,28 @@ function readProcFile (pid, options, done) {
stime: parseFloat(infos[12]),
cutime: parseFloat(infos[13]),
cstime: parseFloat(infos[14]),
start: parseFloat(infos[19]) / cpu.clockTick,
start: parseFloat(infos[19]) / cpuInfo.clockTick,
rss: parseFloat(infos[21]),
uptime: cpu.uptime
uptime: cpuInfo.uptime
}

var memory = stat.rss * cpu.pageSize
var memory = stat.rss * cpuInfo.pageSize

// https://stackoverflow.com/a/16736599/3921589
var childrens = options.childrens ? stat.cutime + stat.cstime : 0
// process usage since last call in seconds
var total = (stat.stime - (hst.stime || 0) + stat.utime - (hst.utime || 0) + childrens) / cpu.clockTick
var total = (stat.stime - (hst.stime || 0) + stat.utime - (hst.utime || 0) + childrens) / cpuInfo.clockTick
// time elapsed between calls in seconds
var seconds = Math.abs(hst.uptime !== undefined ? stat.uptime - hst.uptime : stat.start - stat.uptime)
if (seconds === 0) seconds = 1 // we sure can't divide through 0
var cpu = seconds > 0 ? (total / seconds) * 100 : 0

history.set(stat, options.maxage)

var cpuPercent = Math.min(Math.round((total / seconds) * 100000) / 1000, 100.0)

return done(null, {
cpu: cpuPercent,
cpu: Math.min(cpu, 100.0),
memory: memory,
ctime: (stat.utime + stat.stime) / cpu.clockTick,
ctime: (stat.utime + stat.stime) / cpuInfo.clockTick,
elapsed: date - (stat.start * 1000),
timestamp: stat.start * 1000, // start date
pid: pid,
Expand All @@ -64,10 +63,10 @@ function readProcFile (pid, options, done) {
}

function procfile (pid, options, done) {
updateCpu(cpu, function (err, result) {
updateCpu(cpuInfo, function (err, result) {
if (err) return done(err)

cpu = result
cpuInfo = result
var fns = {}

pid.forEach(function (id, i) {
Expand Down
7 changes: 5 additions & 2 deletions lib/ps.js
Expand Up @@ -4,6 +4,7 @@ var os = require('os')
var bin = require('./bin')

var PLATFORM = os.platform()
var cpus = os.cpus().length

function parseTime (timestr, fraction) {
var time = 0
Expand Down Expand Up @@ -56,6 +57,7 @@ function ps (pids, options, done) {
// ELAPSED: format is [[dd-]hh:]mm:ss
// RSS: is counted as blocks of 1024 bytes
// TIME: format is [[dd-]hh:]mm:ss
// %CPU: goes from 0 to vcore * 100
//
// Refs: http://www.manpages.info/linux/ps.1.html
// NB: The columns are returned in the order given inside the -o option
Expand All @@ -70,6 +72,7 @@ function ps (pids, options, done) {
// ELAPSED: format is [[dd-]hh:]mm:ss
// RSS: is counted as blocks of 1024 bytes
// TIME: format is [[dd-]hh:]ss:mm.pp (pp is the percentage of a minute)
// %CPU: goes from 0 to vcore * 100
//
// Refs: https://ss64.com/osx/ps.html
// NB: The columns are returned in the order given inside the -o option
Expand All @@ -92,13 +95,13 @@ function ps (pids, options, done) {

var pid = parseInt(line[1], 10)
var ppid = parseInt(line[2], 10)
var cpu = parseFloat(line[3].replace(',', '.'), 10)
var cpu = parseFloat(line[3].replace(',', '.'), 10) / cpus
var memory = parseInt(line[4], 10) * 1024
var etime = parseTime(line[0])
var ctime = parseTime(line[5], true)

statistics[pid] = {
cpu: Math.min(Math.round(cpu * 1000) / 1000, 100.0),
cpu: Math.min(cpu, 100.0),
memory: memory,
ppid: ppid,
pid: pid,
Expand Down
8 changes: 4 additions & 4 deletions lib/wmic.js
Expand Up @@ -99,15 +99,15 @@ function wmic (pids, options, done) {
}

// process usage since last call
var total = (kerneltime + usertime - hst.ctime)
// time elapsed between calls
var total = (kerneltime + usertime - hst.ctime) / 1000
// time elapsed between calls in seconds
var seconds = uptime - hst.uptime
var cpu = seconds > 0 ? (total / (seconds * 1000)) * 100 : 0
var cpu = seconds > 0 ? (total / seconds) * 100 : 0

history.set(pid, {ctime: usertime + kerneltime, uptime: uptime}, options.maxage)

statistics[pid] = {
cpu: Math.min(Math.round(cpu * 1000) / 1000, 100.0),
cpu: Math.min(cpu, 100.0),
memory: memory,
ppid: ppid,
pid: pid,
Expand Down
16 changes: 12 additions & 4 deletions test/ps.js
Expand Up @@ -38,8 +38,12 @@ test('should parse ps output on Darwin', async t => {
spawn: () => mocks.spawn(stdout, '', null, 0, null)
})
mockery.registerMock('os', {
EOL: os.EOL, platform: () => 'darwin', type: () => 'type', release: () => 'release'}
)
EOL: os.EOL,
platform: () => 'darwin',
type: () => 'type',
release: () => 'release',
cpus: () => [os.cpus()[0]]
})

const ps = require('../lib/ps')

Expand Down Expand Up @@ -99,8 +103,12 @@ test('should parse ps output on *nix', async t => {
spawn: () => mocks.spawn(stdout, '', null, 0, null)
})
mockery.registerMock('os', {
EOL: os.EOL, platform: () => 'linux', type: () => 'type', release: () => 'release'}
)
EOL: os.EOL,
platform: () => 'linux',
type: () => 'type',
release: () => 'release',
cpus: () => [os.cpus()[0]]
})

const ps = require('../lib/ps')

Expand Down

0 comments on commit 88972d8

Please sign in to comment.