Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
cbbe95e
net: introduce `Socket#connecting` property
indutny Apr 26, 2016
19fb134
doc: use Buffer.from() instead of new Buffer()
JacksonTian Apr 25, 2016
36207c6
doc: correctly document the behavior of ee.once().
lance Apr 25, 2016
11e7cc5
build: don't compile with -B
bnoordhuis Apr 26, 2016
7b9ae70
benchmark: Fix crash in net benchmarks
Apr 27, 2016
8956432
build: exclude tap files from tarballs
mscdex Apr 22, 2016
f6d7279
doc: update build instructions for OS X
Trott Apr 20, 2016
fdde369
crypto: fix error in deprecation message
Trott Apr 22, 2016
6d1606e
test,tools: adjust function argument alignment
Trott Apr 26, 2016
3f608b1
tools: lint for function argument alignment
Trott Apr 19, 2016
66903f6
tools: add tests for the doctool
iankronquist Apr 3, 2016
089362f
test,tools: limit lint tolerance of gc global
Trott Apr 21, 2016
7153f96
build: unbreak -prof, disable PIE on OS X
bnoordhuis Apr 28, 2016
e62c42b
tools: remove default parameters from lint rule
Trott Apr 27, 2016
fa9d82d
src: unify implementations of Utf8Value etc.
addaleax Apr 23, 2016
ab84d69
doc: better example & synopsis
Fishrock123 Apr 12, 2016
150dd36
doc: no Node.js(1)
Fishrock123 Apr 12, 2016
fc0fbf1
doc: subdivide TOC, add auxiliary links
Fishrock123 Apr 12, 2016
9f23cb2
tools: fix exit code when linting from CI
mscdex Apr 27, 2016
2c92a1f
events: pass the original listener added by once
davidtaikocha Apr 29, 2016
1b9fdba
process: add process.cpuUsage() - implementation, doc, tests
Apr 5, 2016
b3f75ec
doc: expand documentation for process.exit()
jasnell Apr 27, 2016
76c9ab5
assert: allow circular references
Trott Apr 27, 2016
fd37d54
doc: added note warning about change to console.endTime()
ben-page Apr 28, 2016
8eb87ee
doc: Remove extra space in REPL example
Apr 28, 2016
bfcde97
doc: fix incorrect syntax in examples
evanlucas Apr 29, 2016
4068d64
doc: fix EventEmitter#eventNames() example
ChALkeR Apr 27, 2016
0d19853
build: use shorthand lint target from test
jbergstroem Apr 27, 2016
e6c8da4
doc: make `writable.setDefaultEncoding()` return `this`
estliberitas Apr 30, 2016
4ae39f9
doc: remove all scrollbar styling
claudiorodriguez Apr 29, 2016
7034ebe
doc: use `Node.js` in synopsis document
Trott Apr 29, 2016
3d5b732
doc: clarifies http.serverResponse implementation
AllenSH12 Apr 6, 2016
13e6608
doc: extra clarification of historySize option
vsemozhetbyt Apr 26, 2016
ab7055b
doc: fix fs.realpath man pg links
phette23 Apr 28, 2016
969f96a
doc: fix a typo in __dirname section
toyota790 Apr 29, 2016
3e028a1
doc: remove obsolete comment in isError() example
cjihrig Apr 30, 2016
e5ce53a
doc: fix sentence fragment in fs doc
Trott Apr 30, 2016
457d12a
test: add failing url parse tests as known_issue
jasnell Mar 24, 2016
5fe5fa2
test: make addon testing part of `make test`
bnoordhuis Apr 15, 2016
2d503b1
debugger: display array contents in repl
cjihrig Apr 28, 2016
7641f9a
test: refactor large event emitter tests
cjihrig Apr 28, 2016
7c30f15
doc: ensure consistent grammar in node.1 file
justshiv Apr 27, 2016
08e0884
tools: add -F flag for fixing lint issues
Trott Apr 29, 2016
1330496
cluster: remove use of bind() in destroy()
yorkie May 1, 2016
d674493
doc: add missing underscore for markdown italics
May 2, 2016
0bca959
util: fix inspecting of proxy objects
jasnell Apr 29, 2016
9a29b50
doc: fix the lint of an example in cluster.md
yorkie May 2, 2016
4f728df
doc: linkify remaining references to fs.Stats object
Apr 30, 2016
33f24c8
doc: adds 'close' events to fs.ReadStream and fs.WriteStream
May 1, 2016
91ab769
util: truncate inspect array and typed array
jasnell Apr 21, 2016
65b6574
deps: backport IsValid changes from 4e8736d in V8
targos May 3, 2016
e6ab3ec
deps: upgrade openssl sources to 1.0.2h
May 3, 2016
3af28d3
deps: copy all openssl header files to include dir
May 3, 2016
d159462
deps: fix openssl assembly error on ia32 win32
indutny Jan 8, 2014
3fe6812
deps: fix asm build error of openssl in x86_win32
Feb 13, 2015
534f03c
openssl: fix keypress requirement in apps on win32
Feb 17, 2015
a5a2944
deps: add -no_rand_screen to openssl s_client
May 27, 2015
54f8600
deps: update openssl asm and asm_obsolete files
May 3, 2016
65030c7
test: fix alpn tests for openssl1.0.2h
May 3, 2016
cd7b76e
2016-05-05, Version 6.1.0 (Current)
Fishrock123 May 5, 2016
8aa8f18
Working on v6.1.1
Fishrock123 May 5, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
process: add process.cpuUsage() - implementation, doc, tests
Add process.cpuUsage() method that returns the user and system
CPU time usage of the current process

PR-URL: #6157
Reviewed-By: Robert Lindstaedt <robert.lindstaedt@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
  • Loading branch information
Patrick Mueller authored and Fishrock123 committed May 4, 2016
commit 1b9fdba04e350ef534a70a1f17d9604285f52100
23 changes: 23 additions & 0 deletions doc/api/process.md
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,29 @@ the value of `process.config`.*

If `process.connected` is `false`, it is no longer possible to send messages.

## process.cpuUsage([previousValue])

Returns the user and system CPU time usage of the current process, in an object
with properties `user` and `system`, whose values are microsecond values
(millionth of a second). These values measure time spent in user and
system code respectively, and may end up being greater than actual elapsed time
if multiple CPU cores are performing work for this process.

The result of a previous call to `process.cpuUsage()` can be passed as the
argument to the function, to get a diff reading.

```js
const startUsage = process.cpuUsage();
// { user: 38579, system: 6986 }

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

console.log(process.cpuUsage(startUsage));
// { user: 514883, system: 11226 }
```

## process.cwd()

Returns the current working directory of the process.
Expand Down
1 change: 1 addition & 0 deletions lib/internal/bootstrap_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
const _process = NativeModule.require('internal/process');

_process.setup_hrtime();
_process.setup_cpuUsage();
_process.setupConfig(NativeModule._source);
NativeModule.require('internal/process/warning').setup();
NativeModule.require('internal/process/next_tick').setup();
Expand Down
52 changes: 52 additions & 0 deletions lib/internal/process.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ function lazyConstants() {
return _lazyConstants;
}

exports.setup_cpuUsage = setup_cpuUsage;
exports.setup_hrtime = setup_hrtime;
exports.setupConfig = setupConfig;
exports.setupKillAndExit = setupKillAndExit;
Expand All @@ -22,6 +23,57 @@ const assert = process.assert = function(x, msg) {
};


// Set up the process.cpuUsage() function.
function setup_cpuUsage() {
// Get the native function, which will be replaced with a JS version.
const _cpuUsage = process.cpuUsage;

// Create the argument array that will be passed to the native function.
const cpuValues = new Float64Array(2);

// Replace the native function with the JS version that calls the native
// function.
process.cpuUsage = function cpuUsage(prevValue) {
// If a previous value was passed in, ensure it has the correct shape.
if (prevValue) {
if (!previousValueIsValid(prevValue.user)) {
throw new TypeError('value of user property of argument is invalid');
}

if (!previousValueIsValid(prevValue.system)) {
throw new TypeError('value of system property of argument is invalid');
}
}

// Call the native function to get the current values.
const errmsg = _cpuUsage(cpuValues);
if (errmsg) {
throw new Error('unable to obtain CPU usage: ' + errmsg);
}

// If a previous value was passed in, return diff of current from previous.
if (prevValue) return {
user: cpuValues[0] - prevValue.user,
system: cpuValues[1] - prevValue.system
};

// If no previous value passed in, return current value.
return {
user: cpuValues[0],
system: cpuValues[1]
};

// Ensure that a previously passed in value is valid. Currently, the native
// implementation always returns numbers <= Number.MAX_SAFE_INTEGER.
function previousValueIsValid(num) {
return Number.isFinite(num) &&
num <= Number.MAX_SAFE_INTEGER &&
num >= 0;
}
};
}


function setup_hrtime() {
const _hrtime = process.hrtime;
const hrValues = new Uint32Array(3);
Expand Down
35 changes: 35 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ using v8::Boolean;
using v8::Context;
using v8::EscapableHandleScope;
using v8::Exception;
using v8::Float64Array;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
Expand Down Expand Up @@ -2220,6 +2221,38 @@ void Hrtime(const FunctionCallbackInfo<Value>& args) {
fields[2] = t % NANOS_PER_SEC;
}

// Microseconds in a second, as a float, used in CPUUsage() below
#define MICROS_PER_SEC 1e6

// CPUUsage use libuv's uv_getrusage() this-process resource usage accessor,
// to access ru_utime (user CPU time used) and ru_stime (system CPU time used),
// which are uv_timeval_t structs (long tv_sec, long tv_usec).
// Returns those values as Float64 microseconds in the elements of the array
// passed to the function.
void CPUUsage(const FunctionCallbackInfo<Value>& args) {
uv_rusage_t rusage;

// Call libuv to get the values we'll return.
int err = uv_getrusage(&rusage);
if (err) {
// On error, return the strerror version of the error code.
Local<String> errmsg = OneByteString(args.GetIsolate(), uv_strerror(err));
args.GetReturnValue().Set(errmsg);
return;
}

// Get the double array pointer from the Float64Array argument.
CHECK(args[0]->IsFloat64Array());
Local<Float64Array> array = args[0].As<Float64Array>();
CHECK_EQ(array->Length(), 2);
Local<ArrayBuffer> ab = array->Buffer();
double* fields = static_cast<double*>(ab->GetContents().Data());

// Set the Float64Array elements to be user / system values in microseconds.
fields[0] = MICROS_PER_SEC * rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec;
fields[1] = MICROS_PER_SEC * rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec;
}

extern "C" void node_module_register(void* m) {
struct node_module* mp = reinterpret_cast<struct node_module*>(m);

Expand Down Expand Up @@ -3212,6 +3245,8 @@ void SetupProcessObject(Environment* env,

env->SetMethod(process, "hrtime", Hrtime);

env->SetMethod(process, "cpuUsage", CPUUsage);

env->SetMethod(process, "dlopen", DLOpen);

env->SetMethod(process, "uptime", Uptime);
Expand Down
63 changes: 63 additions & 0 deletions test/parallel/test-process-cpuUsage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'use strict';
require('../common');
const assert = require('assert');

const result = process.cpuUsage();

// Validate the result of calling with no previous value argument.
validateResult(result);

// Validate the result of calling with a previous value argument.
validateResult(process.cpuUsage(result));

// Ensure the results are >= the previous.
let thisUsage;
let lastUsage = process.cpuUsage();
for (let i = 0; i < 10; i++) {
thisUsage = process.cpuUsage();
validateResult(thisUsage);
assert(thisUsage.user >= lastUsage.user);
assert(thisUsage.system >= lastUsage.system);
lastUsage = thisUsage;
}

// Ensure that the diffs are >= 0.
let startUsage;
let diffUsage;
for (let i = 0; i < 10; i++) {
startUsage = process.cpuUsage();
diffUsage = process.cpuUsage(startUsage);
validateResult(startUsage);
validateResult(diffUsage);
assert(diffUsage.user >= 0);
assert(diffUsage.system >= 0);
}

// Ensure that an invalid shape for the previous value argument throws an error.
assert.throws(function() { process.cpuUsage(1); });
assert.throws(function() { process.cpuUsage({}); });
assert.throws(function() { process.cpuUsage({ user: 'a' }); });
assert.throws(function() { process.cpuUsage({ system: 'b' }); });
assert.throws(function() { process.cpuUsage({ user: null, system: 'c' }); });
assert.throws(function() { process.cpuUsage({ user: 'd', system: null }); });
assert.throws(function() { process.cpuUsage({ user: -1, system: 2 }); });
assert.throws(function() { process.cpuUsage({ user: 3, system: -2 }); });
assert.throws(function() { process.cpuUsage({
user: Number.POSITIVE_INFINITY,
system: 4
});});
assert.throws(function() { process.cpuUsage({
user: 5,
system: Number.NEGATIVE_INFINITY
});});

// Ensure that the return value is the expected shape.
function validateResult(result) {
assert.notEqual(result, null);

assert(Number.isFinite(result.user));
assert(Number.isFinite(result.system));

assert(result.user >= 0);
assert(result.system >= 0);
}
30 changes: 30 additions & 0 deletions test/pummel/test-process-cpuUsage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';
require('../common');
const assert = require('assert');

const start = process.cpuUsage();

// Run a busy-loop for specified # of milliseconds.
const RUN_FOR_MS = 500;

// Define slop factor for checking maximum expected diff values.
const SLOP_FACTOR = 2;

// Run a busy loop.
const now = Date.now();
while (Date.now() - now < RUN_FOR_MS);

// Get a diff reading from when we started.
const diff = process.cpuUsage(start);

const MICROSECONDS_PER_SECOND = 1000 * 1000;

// Diff usages should be >= 0, <= ~RUN_FOR_MS millis.
// Let's be generous with the slop factor, defined above, in case other things
// are happening on this CPU. The <= check may be invalid if the node process
// is making use of multiple CPUs, in which case, just remove it.
assert(diff.user >= 0);
assert(diff.user <= SLOP_FACTOR * RUN_FOR_MS * MICROSECONDS_PER_SECOND);

assert(diff.system >= 0);
assert(diff.system <= SLOP_FACTOR * RUN_FOR_MS * MICROSECONDS_PER_SECOND);