Skip to content

Commit

Permalink
perf_hooks: reduce overhead of createHistogram
Browse files Browse the repository at this point in the history
PR-URL: #50074
Reviewed-By: Stephen Belanger <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Rafael Gonzaga <[email protected]>
  • Loading branch information
H4ad authored and targos committed Nov 11, 2023
1 parent 766bd9c commit 905ca00
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 20 deletions.
24 changes: 24 additions & 0 deletions benchmark/perf_hooks/histogram-clone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

const assert = require('assert');
const common = require('../common.js');

const { createHistogram } = require('perf_hooks');

const bench = common.createBenchmark(main, {
n: [1e5],
});

let _histogram;

function main({ n }) {
const histogram = createHistogram();

bench.start();
for (let i = 0; i < n; i++)
_histogram = structuredClone(histogram);
bench.end(n);

// Avoid V8 deadcode (elimination)
assert.ok(_histogram);
}
22 changes: 22 additions & 0 deletions benchmark/perf_hooks/histogram-create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict';

const assert = require('assert');
const common = require('../common.js');

const { createHistogram } = require('perf_hooks');

const bench = common.createBenchmark(main, {
n: [1e5],
});

let _histogram;

function main({ n }) {
bench.start();
for (let i = 0; i < n; i++)
_histogram = createHistogram();
bench.end(n);

// Avoid V8 deadcode (elimination)
assert.ok(_histogram);
}
56 changes: 36 additions & 20 deletions lib/internal/histogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,13 @@ function isHistogram(object) {
return object?.[kHandle] !== undefined;
}

const kSkipThrow = Symbol('kSkipThrow');

class Histogram {
constructor() {
throw new ERR_ILLEGAL_CONSTRUCTOR();
constructor(skipThrowSymbol = undefined) {
if (skipThrowSymbol !== kSkipThrow) {
throw new ERR_ILLEGAL_CONSTRUCTOR();
}
}

[kInspect](depth, options) {
Expand Down Expand Up @@ -242,7 +246,7 @@ class Histogram {
const handle = this[kHandle];
return {
data: { handle },
deserializeInfo: 'internal/histogram:internalHistogram',
deserializeInfo: 'internal/histogram:ClonedHistogram',
};
}

Expand All @@ -264,8 +268,12 @@ class Histogram {
}

class RecordableHistogram extends Histogram {
constructor() {
throw new ERR_ILLEGAL_CONSTRUCTOR();
constructor(skipThrowSymbol = undefined) {
if (skipThrowSymbol !== kSkipThrow) {
throw new ERR_ILLEGAL_CONSTRUCTOR();
}

super(skipThrowSymbol);
}

/**
Expand Down Expand Up @@ -309,7 +317,7 @@ class RecordableHistogram extends Histogram {
const handle = this[kHandle];
return {
data: { handle },
deserializeInfo: 'internal/histogram:internalRecordableHistogram',
deserializeInfo: 'internal/histogram:ClonedRecordableHistogram',
};
}

Expand All @@ -318,26 +326,34 @@ class RecordableHistogram extends Histogram {
}
}

function internalHistogram(handle) {
function ClonedHistogram(handle) {
return ReflectConstruct(
function() {
markTransferMode(this, true, false);
this[kHandle] = handle;
this[kMap] = new SafeMap();
}, [], Histogram);
}
internalHistogram.prototype[kDeserialize] = () => {};

function internalRecordableHistogram(handle) {
return ReflectConstruct(
function() {
markTransferMode(this, true, false);
this[kHandle] = handle;
this[kMap] = new SafeMap();
this[kRecordable] = true;
}, [], RecordableHistogram);
ClonedHistogram.prototype[kDeserialize] = () => { };

function ClonedRecordableHistogram(handle) {
const histogram = new RecordableHistogram(kSkipThrow);

markTransferMode(histogram, true, false);
histogram[kRecordable] = true;
histogram[kMap] = new SafeMap();
histogram[kHandle] = handle;
histogram.constructor = RecordableHistogram;

return histogram;
}

ClonedRecordableHistogram.prototype[kDeserialize] = () => { };

function createRecordableHistogram(handle) {
return new ClonedRecordableHistogram(handle);
}
internalRecordableHistogram.prototype[kDeserialize] = () => {};

/**
* @param {{
Expand All @@ -363,14 +379,14 @@ function createHistogram(options = kEmptyObject) {
throw new ERR_INVALID_ARG_VALUE.RangeError('options.highest', highest);
}
validateInteger(figures, 'options.figures', 1, 5);
return internalRecordableHistogram(new _Histogram(lowest, highest, figures));
return createRecordableHistogram(new _Histogram(lowest, highest, figures));
}

module.exports = {
Histogram,
RecordableHistogram,
internalHistogram,
internalRecordableHistogram,
ClonedHistogram,
ClonedRecordableHistogram,
isHistogram,
kDestroy,
kHandle,
Expand Down

0 comments on commit 905ca00

Please sign in to comment.