Skip to content

Commit

Permalink
perf_hooks: introduce createHistogram
Browse files Browse the repository at this point in the history
Adds a new `perf_hooks.createHistogram()` API for creating histogram
instances that allow user recording.

Makes Histogram instances cloneable via MessagePort. This allows, for
instance, an event loop delay monitor to be running on the main thread
while the histogram data can be monitored actively from a worker thread.

Signed-off-by: James M Snell <jasnell@gmail.com>

PR-URL: #37155
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
jasnell authored and MylesBorins committed Aug 31, 2021
1 parent 32de361 commit 4a88dde
Show file tree
Hide file tree
Showing 15 changed files with 774 additions and 322 deletions.
114 changes: 78 additions & 36 deletions doc/api/perf_hooks.md
Expand Up @@ -651,6 +651,22 @@ performance.mark('test');
performance.mark('meow');
```

## `perf_hooks.createHistogram([options])`
<!-- YAML
added: REPLACEME
-->

* `options` {Object}
* `min` {number|bigint} The minimum recordable value. Must be an integer
value greater than 0. **Defaults**: `1`.
* `max` {number|bigint} The maximum recordable value. Must be an integer
value greater than `min`. **Defaults**: `Number.MAX_SAFE_INTEGER`.
* `figures` {number} The number of accuracy digits. Must be a number between
`1` and `5`. **Defaults**: `3`.
* Returns {RecordableHistogram}

Returns a {RecordableHistogram}.

## `perf_hooks.monitorEventLoopDelay([options])`
<!-- YAML
added: v11.10.0
Expand All @@ -659,12 +675,12 @@ added: v11.10.0
* `options` {Object}
* `resolution` {number} The sampling rate in milliseconds. Must be greater
than zero. **Default:** `10`.
* Returns: {Histogram}
* Returns: {IntervalHistogram}

_This property is an extension by Node.js. It is not available in Web browsers._

Creates a `Histogram` object that samples and reports the event loop delay
over time. The delays will be reported in nanoseconds.
Creates an `IntervalHistogram` object that samples and reports the event loop
delay over time. The delays will be reported in nanoseconds.

Using a timer to detect approximate event loop delay works because the
execution of timers is tied specifically to the lifecycle of the libuv
Expand All @@ -687,36 +703,12 @@ console.log(h.percentile(50));
console.log(h.percentile(99));
```

### Class: `Histogram`
<!-- YAML
added: v11.10.0
-->
Tracks the event loop delay at a given sampling rate. The constructor of
this class not exposed to users.

_This property is an extension by Node.js. It is not available in Web browsers._

#### `histogram.disable()`
<!-- YAML
added: v11.10.0
-->

* Returns: {boolean}

Disables the event loop delay sample timer. Returns `true` if the timer was
stopped, `false` if it was already stopped.

#### `histogram.enable()`
## Class: `Histogram`
<!-- YAML
added: v11.10.0
-->

* Returns: {boolean}

Enables the event loop delay sample timer. Returns `true` if the timer was
started, `false` if it was already started.

#### `histogram.exceeds`
### `histogram.exceeds`
<!-- YAML
added: v11.10.0
-->
Expand All @@ -726,7 +718,7 @@ added: v11.10.0
The number of times the event loop delay exceeded the maximum 1 hour event
loop delay threshold.

#### `histogram.max`
### `histogram.max`
<!-- YAML
added: v11.10.0
-->
Expand All @@ -735,7 +727,7 @@ added: v11.10.0

The maximum recorded event loop delay.

#### `histogram.mean`
### `histogram.mean`
<!-- YAML
added: v11.10.0
-->
Expand All @@ -744,7 +736,7 @@ added: v11.10.0

The mean of the recorded event loop delays.

#### `histogram.min`
### `histogram.min`
<!-- YAML
added: v11.10.0
-->
Expand All @@ -753,7 +745,7 @@ added: v11.10.0

The minimum recorded event loop delay.

#### `histogram.percentile(percentile)`
### `histogram.percentile(percentile)`
<!-- YAML
added: v11.10.0
-->
Expand All @@ -763,7 +755,7 @@ added: v11.10.0

Returns the value at the given percentile.

#### `histogram.percentiles`
### `histogram.percentiles`
<!-- YAML
added: v11.10.0
-->
Expand All @@ -772,14 +764,14 @@ added: v11.10.0

Returns a `Map` object detailing the accumulated percentile distribution.

#### `histogram.reset()`
### `histogram.reset()`
<!-- YAML
added: v11.10.0
-->

Resets the collected histogram data.

#### `histogram.stddev`
### `histogram.stddev`
<!-- YAML
added: v11.10.0
-->
Expand All @@ -788,6 +780,56 @@ added: v11.10.0

The standard deviation of the recorded event loop delays.

## Class: `IntervalHistogram extends Histogram`

A `Histogram` that is periodically updated on a given interval.

### `histogram.disable()`
<!-- YAML
added: v11.10.0
-->

* Returns: {boolean}

Disables the update interval timer. Returns `true` if the timer was
stopped, `false` if it was already stopped.

### `histogram.enable()`
<!-- YAML
added: v11.10.0
-->

* Returns: {boolean}

Enables the update interval timer. Returns `true` if the timer was
started, `false` if it was already started.

### Cloning an `IntervalHistogram`

{IntervalHistogram} instances can be cloned via {MessagePort}. On the receiving
end, the histogram is cloned as a plain {Histogram} object that does not
implement the `enable()` and `disable()` methods.

## Class: `RecordableHistogram extends Histogram`
<!-- YAML
added: REPLACEME
-->

### `histogram.record(val)`
<!-- YAML
added: REPLACEME
-->

* `val` {number|bigint} The amount to record in the histogram.

### `histogram.recordDelta()`
<!-- YAML
added: REPLACEME
-->

Calculates the amount of time (in nanoseconds) that has passed since the
previous call to `recordDelta()` and records that amount in the histogram.

## Examples

### Measuring the duration of async operations
Expand Down
4 changes: 4 additions & 0 deletions doc/api/worker_threads.md
Expand Up @@ -381,6 +381,9 @@ changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/37917
description: Add 'BlockList' to the list of cloneable types.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/37155
description: Add 'Histogram' types to the list of cloneable types.
- version: v14.5.0
pr-url: https://github.com/nodejs/node/pull/33360
description: Added `KeyObject` to the list of cloneable types.
Expand All @@ -406,6 +409,7 @@ In particular, the significant differences to `JSON` are:
* `value` may contain [`WebAssembly.Module`][] instances.
* `value` may not contain native (C++-backed) objects other than:
* {FileHandle}s,
* {Histogram}s,
* {KeyObject}s,
* {MessagePort}s,
* {net.BlockList}s,
Expand Down

0 comments on commit 4a88dde

Please sign in to comment.