Files
node/lib/internal/perf/event_loop_delay.js
T
James M Snell bfa3e982ec lib,src: improve histogram implementation
Several improvements:

1. In histogram-inl, Add previous locked only this->mutex while
   reading the other's fields unsafely.
2. In histogram.cc, PrepareCB now uses ContainerOf
3. In histogram.cc, BigInt value range is checked
4. In histogram.js, simplified impl and reduced duplication
5. In event_loop_delay.js, use a more consistent constructor

Adds new analytical APIs to Histogram

* histogram.ccdf(value)
* histogram.cdf(value)
* histogram.countAt(value)
* histogram.ksTest(other)
* histogram.kurtosis
* histogram.linearBuckets(stepSize)
* histogram.logBuckets(first, base)
* histogram.percentilesAt(percentiles)
* histogram.shewness

On RecordableHistogram

* histogram.recordCorrected(val, expectedInterval)
* histogram.subtract(other)

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode/Opus
PR-URL: https://github.com/nodejs/node/pull/65024
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-08-12 07:41:57 -07:00

99 lines
2.0 KiB
JavaScript

'use strict';
const {
Symbol,
SymbolDispose,
} = primordials;
const {
codes: {
ERR_ILLEGAL_CONSTRUCTOR,
ERR_INVALID_THIS,
},
} = require('internal/errors');
const {
createELDHistogram,
} = internalBinding('performance');
const {
validateBoolean,
validateInteger,
validateObject,
} = require('internal/validators');
const {
Histogram,
kHandle,
kSkipThrow,
} = require('internal/histogram');
const {
kEmptyObject,
} = require('internal/util');
const {
markTransferMode,
} = require('internal/worker/js_transferable');
const kEnabled = Symbol('kEnabled');
class ELDHistogram extends Histogram {
constructor(skipThrowSymbol = undefined) {
if (skipThrowSymbol !== kSkipThrow) {
throw new ERR_ILLEGAL_CONSTRUCTOR();
}
super(skipThrowSymbol);
}
/**
* @returns {boolean}
*/
enable() {
if (this[kEnabled] === undefined)
throw new ERR_INVALID_THIS('ELDHistogram');
if (this[kEnabled]) return false;
this[kEnabled] = true;
this[kHandle].start();
return true;
}
/**
* @returns {boolean}
*/
disable() {
if (this[kEnabled] === undefined)
throw new ERR_INVALID_THIS('ELDHistogram');
if (!this[kEnabled]) return false;
this[kEnabled] = false;
this[kHandle].stop();
return true;
}
[SymbolDispose]() {
this.disable();
}
}
/**
* @param {{
* samplePerIteration : boolean,
* resolution : number
* }} [options]
* @returns {ELDHistogram}
*/
function monitorEventLoopDelay(options = kEmptyObject) {
validateObject(options, 'options');
const { samplePerIteration = false, resolution = 10 } = options;
validateBoolean(samplePerIteration, 'options.samplePerIteration');
validateInteger(resolution, 'options.resolution', 1);
const histogram = new ELDHistogram(kSkipThrow);
markTransferMode(histogram, true, false);
histogram[kEnabled] = false;
histogram[kHandle] = createELDHistogram(resolution, samplePerIteration);
return histogram;
}
module.exports = monitorEventLoopDelay;