summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvmarchaud <contact@vmarchaud.fr>2019-06-02 13:33:47 +0200
committerAnna Henningsen <anna@addaleax.net>2019-07-01 16:02:17 +0200
commit6271ef005eb311c819b7ab041e09f50e4155ec1e (patch)
treee16ef8aa0f1db3fcdcd6cd1405ddf4412da18a2d
parent20d099af7a1fc103ecfb9a4afe59fd2fdcbe7802 (diff)
downloadandroid-node-v8-6271ef005eb311c819b7ab041e09f50e4155ec1e.tar.gz
android-node-v8-6271ef005eb311c819b7ab041e09f50e4155ec1e.tar.bz2
android-node-v8-6271ef005eb311c819b7ab041e09f50e4155ec1e.zip
process: expose uv_rusage on process.resourcesUsage()
As discussed in https://github.com/nodejs/diagnostics/issues/161, the core should expose important metrics about the runtime, this PR's goal is to let user get the number of io request made, and lower level mertrics like the page faults and context switches. PR-URL: https://github.com/nodejs/node/pull/28018 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
-rw-r--r--doc/api/process.md89
-rw-r--r--lib/internal/bootstrap/node.js1
-rw-r--r--lib/internal/process/per_thread.js27
-rw-r--r--src/node_process_methods.cc33
-rw-r--r--test/parallel/test-resource-usage.js27
5 files changed, 176 insertions, 1 deletions
diff --git a/doc/api/process.md b/doc/api/process.md
index 752889b3f0..ec48906d5c 100644
--- a/doc/api/process.md
+++ b/doc/api/process.md
@@ -1815,6 +1815,91 @@ process.report.writeReport();
Additional documentation is available in the [report documentation][].
+## process.resourceUsage()
+<!-- YAML
+added: REPLACEME
+-->
+
+* Returns: {Object}
+ * `userCPUTime` {integer}
+ * `systemCPUTime` {integer}
+ * `maxRSS` {integer}
+ * `sharedMemorySize` {integer}
+ * `unsharedDataSize` {integer}
+ * `unsharedStackSize` {integer}
+ * `minorPageFault` {integer}
+ * `majorPageFault` {integer}
+ * `swapedOut` {integer}
+ * `fsRead` {integer}
+ * `fsWrite` {integer}
+ * `ipcSent` {integer}
+ * `ipcReceived` {integer}
+ * `signalsCount` {integer}
+ * `voluntaryContextSwitches` {integer}
+ * `involuntaryContextSwitches` {integer}
+
+The `process.resourceUsage()` method returns the resource usage
+for the current process.
+All of these values come from the `uv_getrusage` call which returns
+[this struct][uv_rusage_t], here the mapping between node and libuv:
+- `userCPUTime` maps to `ru_utime` computed in microseconds.
+It is the values as [`process.cpuUsage().user`][process.cpuUsage]
+- `systemCPUTime` maps to `ru_stime` computed in microseconds.
+It is the value as [`process.cpuUsage().system`][process.cpuUsage]
+- `maxRSS` maps to `ru_maxrss` which is the maximum resident set size
+used (in kilobytes).
+- `sharedMemorySize` maps to `ru_ixrss` but is not supported by any platform.
+- `unsharedDataSize` maps to `ru_idrss` but is not supported by any platform.
+- `unsharedStackSize` maps to `ru_isrss` but is not supported by any platform.
+- `minorPageFault` maps to `ru_minflt` which is the number of minor page fault
+for the process, see [this article for more details][wikipedia_minor_fault]
+- `majorPageFault` maps to `ru_majflt` which is the number of major page fault
+for the process, see [this article for more details][wikipedia_major_fault].
+This field is not supported on Windows platforms.
+- `swappedOut` maps to `ru_nswap` which is not supported by any platform.
+- `fsRead` maps to `ru_inblock` which is the number of times the file system
+had to perform input.
+- `fsWrite` maps to `ru_oublock` which is the number of times the file system
+had to perform output.
+- `ipcSent` maps to `ru_msgsnd` but is not supported by any platform.
+- `ipcReceived` maps to `ru_msgrcv` but is not supported by any platform.
+- `signalsCount` maps to `ru_nsignals` but is not supported by any platform.
+- `voluntaryContextSwitches` maps to `ru_nvcsw` which is the number of times
+a CPU context switch resulted due to a process voluntarily giving up the
+processor before its time slice was completed
+(usually to await availability of a resource).
+This field is not supported on Windows platforms.
+- `involuntaryContextSwitches` maps to `ru_nivcsw` which is the number of times
+a CPU context switch resulted due to a higher priority process becoming runnable
+ or because the current process exceeded its time slice.
+This field is not supported on Windows platforms.
+
+
+```js
+console.log(process.resourceUsage());
+/*
+ Will output:
+ {
+ userCPUTime: 82872,
+ systemCPUTime: 4143,
+ maxRSS: 33164,
+ sharedMemorySize: 0,
+ unsharedDataSize: 0,
+ unsharedStackSize: 0,
+ minorPageFault: 2469,
+ majorPageFault: 0,
+ swapedOut: 0,
+ fsRead: 0,
+ fsWrite: 8,
+ ipcSent: 0,
+ ipcReceived: 0,
+ signalsCount: 0,
+ voluntaryContextSwitches: 79,
+ involuntaryContextSwitches: 1
+ }
+*/
+```
+
## process.send(message[, sendHandle[, options]][, callback])
<!-- YAML
added: v0.5.9
@@ -2329,6 +2414,10 @@ cases:
[Writable]: stream.html#stream_writable_streams
[debugger]: debugger.html
[note on process I/O]: process.html#process_a_note_on_process_i_o
+[process.cpuUsage]: #process_process_cpuusage_previousvalue
[process_emit_warning]: #process_process_emitwarning_warning_type_code_ctor
[process_warning]: #process_event_warning
[report documentation]: report.html
+[uv_rusage_t]: http://docs.libuv.org/en/v1.x/misc.html#c.uv_rusage_t
+[wikipedia_minor_fault]: https://en.wikipedia.org/wiki/Page_fault#Minor
+[wikipedia_major_fault]: https://en.wikipedia.org/wiki/Page_fault#Major
diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js
index e8735c2049..86b2164bb0 100644
--- a/lib/internal/bootstrap/node.js
+++ b/lib/internal/bootstrap/node.js
@@ -110,6 +110,7 @@ if (isMainThread) {
process.hrtime = wrapped.hrtime;
process.hrtime.bigint = wrapped.hrtimeBigInt;
process.cpuUsage = wrapped.cpuUsage;
+ process.resourceUsage = wrapped.resourceUsage;
process.memoryUsage = wrapped.memoryUsage;
process.kill = wrapped.kill;
process.exit = wrapped.exit;
diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js
index 2204d7223b..63ebf2afb6 100644
--- a/lib/internal/process/per_thread.js
+++ b/lib/internal/process/per_thread.js
@@ -35,7 +35,8 @@ function wrapProcessMethods(binding) {
hrtime: _hrtime,
hrtimeBigInt: _hrtimeBigInt,
cpuUsage: _cpuUsage,
- memoryUsage: _memoryUsage
+ memoryUsage: _memoryUsage,
+ resourceUsage: _resourceUsage
} = binding;
function _rawDebug(...args) {
@@ -190,12 +191,36 @@ function wrapProcessMethods(binding) {
return true;
}
+ const resourceValues = new Float64Array(16);
+ function resourceUsage() {
+ _resourceUsage(resourceValues);
+ return {
+ userCPUTime: resourceValues[0],
+ systemCPUTime: resourceValues[1],
+ maxRSS: resourceValues[2],
+ sharedMemorySize: resourceValues[3],
+ unsharedDataSize: resourceValues[4],
+ unsharedStackSize: resourceValues[5],
+ minorPageFault: resourceValues[6],
+ majorPageFault: resourceValues[7],
+ swappedOut: resourceValues[8],
+ fsRead: resourceValues[9],
+ fsWrite: resourceValues[10],
+ ipcSent: resourceValues[11],
+ ipcReceived: resourceValues[12],
+ signalsCount: resourceValues[13],
+ voluntaryContextSwitches: resourceValues[14],
+ involuntaryContextSwitches: resourceValues[15]
+ };
+ }
+
return {
_rawDebug,
hrtime,
hrtimeBigInt,
cpuUsage,
+ resourceUsage,
memoryUsage,
kill,
exit
diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc
index b34cbf89b6..3a2c1efd81 100644
--- a/src/node_process_methods.cc
+++ b/src/node_process_methods.cc
@@ -285,6 +285,38 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) {
Array::New(env->isolate(), handle_v.data(), handle_v.size()));
}
+static void ResourceUsage(const FunctionCallbackInfo<Value>& args) {
+ Environment* env = Environment::GetCurrent(args);
+
+ uv_rusage_t rusage;
+ int err = uv_getrusage(&rusage);
+ if (err)
+ return env->ThrowUVException(err, "uv_getrusage");
+
+ CHECK(args[0]->IsFloat64Array());
+ Local<Float64Array> array = args[0].As<Float64Array>();
+ CHECK_EQ(array->Length(), 16);
+ Local<ArrayBuffer> ab = array->Buffer();
+ double* fields = static_cast<double*>(ab->GetContents().Data());
+
+ 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;
+ fields[2] = rusage.ru_maxrss;
+ fields[3] = rusage.ru_ixrss;
+ fields[4] = rusage.ru_idrss;
+ fields[5] = rusage.ru_isrss;
+ fields[6] = rusage.ru_minflt;
+ fields[7] = rusage.ru_majflt;
+ fields[8] = rusage.ru_nswap;
+ fields[9] = rusage.ru_inblock;
+ fields[10] = rusage.ru_oublock;
+ fields[11] = rusage.ru_msgsnd;
+ fields[12] = rusage.ru_msgrcv;
+ fields[13] = rusage.ru_nsignals;
+ fields[14] = rusage.ru_nvcsw;
+ fields[15] = rusage.ru_nivcsw;
+}
+
#ifdef __POSIX__
static void DebugProcess(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
@@ -426,6 +458,7 @@ static void InitializeProcessMethods(Local<Object> target,
env->SetMethod(target, "cpuUsage", CPUUsage);
env->SetMethod(target, "hrtime", Hrtime);
env->SetMethod(target, "hrtimeBigInt", HrtimeBigInt);
+ env->SetMethod(target, "resourceUsage", ResourceUsage);
env->SetMethod(target, "_getActiveRequests", GetActiveRequests);
env->SetMethod(target, "_getActiveHandles", GetActiveHandles);
diff --git a/test/parallel/test-resource-usage.js b/test/parallel/test-resource-usage.js
new file mode 100644
index 0000000000..25302b8413
--- /dev/null
+++ b/test/parallel/test-resource-usage.js
@@ -0,0 +1,27 @@
+'use strict';
+require('../common');
+const assert = require('assert');
+
+const rusage = process.resourceUsage();
+
+[
+ 'userCPUTime',
+ 'systemCPUTime',
+ 'maxRSS',
+ 'sharedMemorySize',
+ 'unsharedDataSize',
+ 'unsharedStackSize',
+ 'minorPageFault',
+ 'majorPageFault',
+ 'swappedOut',
+ 'fsRead',
+ 'fsWrite',
+ 'ipcSent',
+ 'ipcReceived',
+ 'signalsCount',
+ 'voluntaryContextSwitches',
+ 'involuntaryContextSwitches'
+].forEach((n) => {
+ assert.strictEqual(typeof rusage[n], 'number', `${n} should be a number`);
+ assert(rusage[n] >= 0, `${n} should be above or equal 0`);
+});