Skip to content

Commit a647d82

Browse files
committed
process: improve process.hrtime
* Add benchmarks for diffing a previous result * Improvements to the documentation, including type annotation * Update the outdated comments in src/node.cc, improve comments in lib/internal/process.js * Check the argument is an Array Tuple with length 2 PR-URL: #10764 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Brian White <[email protected]>
1 parent 9fcd842 commit a647d82

File tree

5 files changed

+65
-38
lines changed

5 files changed

+65
-38
lines changed

benchmark/process/bench-hrtime.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
11
'use strict';
22

33
const common = require('../common');
4+
const assert = require('assert');
45

56
const bench = common.createBenchmark(main, {
6-
n: [1e6]
7+
n: [1e6],
8+
type: ['raw', 'diff']
79
});
810

9-
1011
function main(conf) {
11-
const n = conf.n >>> 0;
12+
const n = conf.n | 0;
13+
const hrtime = process.hrtime;
14+
var noDead = hrtime();
15+
var i;
1216

13-
bench.start();
14-
for (var i = 0; i < n; i++) {
15-
process.hrtime();
17+
if (conf.type === 'raw') {
18+
bench.start();
19+
for (i = 0; i < n; i++) {
20+
noDead = hrtime();
21+
}
22+
bench.end(n);
23+
} else {
24+
bench.start();
25+
for (i = 0; i < n; i++) {
26+
noDead = hrtime(noDead);
27+
}
28+
bench.end(n);
1629
}
17-
bench.end(n);
30+
31+
assert.ok(Array.isArray(noDead));
1832
}

doc/api/process.md

+17-13
Original file line numberDiff line numberDiff line change
@@ -1016,33 +1016,37 @@ Android)
10161016
added: v0.7.6
10171017
-->
10181018

1019-
The `process.hrtime()` method returns the current high-resolution real time in a
1020-
`[seconds, nanoseconds]` tuple Array. `time` is an optional parameter that must
1021-
be the result of a previous `process.hrtime()` call (and therefore, a real time
1022-
in a `[seconds, nanoseconds]` tuple Array containing a previous time) to diff
1023-
with the current time. These times are relative to an arbitrary time in the
1024-
past, and not related to the time of day and therefore not subject to clock
1025-
drift. The primary use is for measuring performance between intervals.
1019+
* `time` {Array} The result of a previous call to `process.hrtime()`
1020+
* Returns: {Array}
1021+
1022+
The `process.hrtime()` method returns the current high-resolution real time
1023+
in a `[seconds, nanoseconds]` tuple Array, where `nanoseconds` is the
1024+
remaining part of the real time that can't be represented in second precision.
10261025

1027-
Passing in the result of a previous call to `process.hrtime()` is useful for
1028-
calculating an amount of time passed between calls:
1026+
`time` is an optional parameter that must be the result of a previous
1027+
`process.hrtime()` call to diff with the current time. If the parameter
1028+
passed in is not a tuple Array, a `TypeError` will be thrown. Passing in a
1029+
user-defined array instead of the result of a previous call to
1030+
`process.hrtime()` will lead to undefined behavior.
1031+
1032+
These times are relative to an arbitrary time in the
1033+
past, and not related to the time of day and therefore not subject to clock
1034+
drift. The primary use is for measuring performance between intervals:
10291035

10301036
```js
1037+
const NS_PER_SEC = 1e9;
10311038
var time = process.hrtime();
10321039
// [ 1800216, 25 ]
10331040

10341041
setTimeout(() => {
10351042
var diff = process.hrtime(time);
10361043
// [ 1, 552 ]
10371044

1038-
console.log(`Benchmark took ${diff[0] * 1e9 + diff[1]} nanoseconds`);
1045+
console.log(`Benchmark took ${diff[0] * NS_PER_SEC + diff[1]} nanoseconds`);
10391046
// benchmark took 1000000527 nanoseconds
10401047
}, 1000);
10411048
```
10421049

1043-
Constructing an array by some method other than calling `process.hrtime()` and
1044-
passing the result to process.hrtime() will result in undefined behavior.
1045-
10461050

10471051
## process.initgroups(user, extra_group)
10481052
<!-- YAML

lib/internal/process.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -73,19 +73,22 @@ function setup_cpuUsage() {
7373
};
7474
}
7575

76-
76+
// The 3 entries filled in by the original process.hrtime contains
77+
// the upper/lower 32 bits of the second part of the value,
78+
// and the renamining nanoseconds of the value.
7779
function setup_hrtime() {
7880
const _hrtime = process.hrtime;
7981
const hrValues = new Uint32Array(3);
8082

81-
process.hrtime = function hrtime(ar) {
83+
process.hrtime = function hrtime(time) {
8284
_hrtime(hrValues);
8385

84-
if (typeof ar !== 'undefined') {
85-
if (Array.isArray(ar)) {
86-
const sec = (hrValues[0] * 0x100000000 + hrValues[1]) - ar[0];
87-
const nsec = hrValues[2] - ar[1];
88-
return [nsec < 0 ? sec - 1 : sec, nsec < 0 ? nsec + 1e9 : nsec];
86+
if (time !== undefined) {
87+
if (Array.isArray(time) && time.length === 2) {
88+
const sec = (hrValues[0] * 0x100000000 + hrValues[1]) - time[0];
89+
const nsec = hrValues[2] - time[1];
90+
const needsBorrow = nsec < 0;
91+
return [needsBorrow ? sec - 1 : sec, needsBorrow ? nsec + 1e9 : nsec];
8992
}
9093

9194
throw new TypeError('process.hrtime() only accepts an Array tuple');
@@ -98,7 +101,6 @@ function setup_hrtime() {
98101
};
99102
}
100103

101-
102104
function setupConfig(_source) {
103105
// NativeModule._source
104106
// used for `process.config`, but not a real module

src/node.cc

+6-6
Original file line numberDiff line numberDiff line change
@@ -2274,18 +2274,18 @@ void Kill(const FunctionCallbackInfo<Value>& args) {
22742274

22752275
// Hrtime exposes libuv's uv_hrtime() high-resolution timer.
22762276
// The value returned by uv_hrtime() is a 64-bit int representing nanoseconds,
2277-
// so this function instead returns an Array with 2 entries representing seconds
2278-
// and nanoseconds, to avoid any integer overflow possibility.
2279-
// Pass in an Array from a previous hrtime() call to instead get a time diff.
2277+
// so this function instead fills in an Uint32Array with 3 entries,
2278+
// to avoid any integer overflow possibility.
2279+
// The first two entries contain the second part of the value
2280+
// broken into the upper/lower 32 bits to be converted back in JS,
2281+
// because there is no Uint64Array in JS.
2282+
// The third entry contains the remaining nanosecond part of the value.
22802283
void Hrtime(const FunctionCallbackInfo<Value>& args) {
22812284
uint64_t t = uv_hrtime();
22822285

22832286
Local<ArrayBuffer> ab = args[0].As<Uint32Array>()->Buffer();
22842287
uint32_t* fields = static_cast<uint32_t*>(ab->GetContents().Data());
22852288

2286-
// These three indices will contain the values for the hrtime tuple. The
2287-
// seconds value is broken into the upper/lower 32 bits and stored in two
2288-
// uint32 fields to be converted back in JS.
22892289
fields[0] = (t / NANOS_PER_SEC) >> 32;
22902290
fields[1] = (t / NANOS_PER_SEC) & 0xffffffff;
22912291
fields[2] = t % NANOS_PER_SEC;

test/parallel/test-process-hrtime.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,21 @@ validateTuple(process.hrtime(tuple));
1515
assert.throws(() => {
1616
process.hrtime(1);
1717
}, /^TypeError: process.hrtime\(\) only accepts an Array tuple$/);
18+
assert.throws(() => {
19+
process.hrtime([]);
20+
}, /^TypeError: process.hrtime\(\) only accepts an Array tuple$/);
21+
assert.throws(() => {
22+
process.hrtime([1]);
23+
}, /^TypeError: process.hrtime\(\) only accepts an Array tuple$/);
24+
assert.throws(() => {
25+
process.hrtime([1, 2, 3]);
26+
}, /^TypeError: process.hrtime\(\) only accepts an Array tuple$/);
1827

1928
function validateTuple(tuple) {
2029
assert(Array.isArray(tuple));
2130
assert.strictEqual(tuple.length, 2);
22-
tuple.forEach((v) => {
23-
assert.strictEqual(typeof v, 'number');
24-
assert.strictEqual(isFinite(v), true);
25-
});
31+
assert(Number.isInteger(tuple[0]));
32+
assert(Number.isInteger(tuple[1]));
2633
}
2734

2835
const diff = process.hrtime([0, 1e9 - 1]);

0 commit comments

Comments
 (0)