Skip to content

Commit 72aabe1

Browse files
H4adRafaelGSS
authored andcommittedApr 10, 2024
perf_hooks: reduce overhead of createHistogram
PR-URL: #50074 Backport-PR-URL: #51306 Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 9d7a204 commit 72aabe1

File tree

3 files changed

+81
-19
lines changed

3 files changed

+81
-19
lines changed
 
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const common = require('../common.js');
5+
6+
const { createHistogram } = require('perf_hooks');
7+
8+
const bench = common.createBenchmark(main, {
9+
n: [1e5],
10+
});
11+
12+
let _histogram;
13+
14+
function main({ n }) {
15+
const histogram = createHistogram();
16+
17+
bench.start();
18+
for (let i = 0; i < n; i++)
19+
_histogram = structuredClone(histogram);
20+
bench.end(n);
21+
22+
// Avoid V8 deadcode (elimination)
23+
assert.ok(_histogram);
24+
}
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const common = require('../common.js');
5+
6+
const { createHistogram } = require('perf_hooks');
7+
8+
const bench = common.createBenchmark(main, {
9+
n: [1e5],
10+
});
11+
12+
let _histogram;
13+
14+
function main({ n }) {
15+
bench.start();
16+
for (let i = 0; i < n; i++)
17+
_histogram = createHistogram();
18+
bench.end(n);
19+
20+
// Avoid V8 deadcode (elimination)
21+
assert.ok(_histogram);
22+
}

‎lib/internal/histogram.js

+35-19
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,13 @@ function isHistogram(object) {
5252
return object?.[kHandle] !== undefined;
5353
}
5454

55+
const kSkipThrow = Symbol('kSkipThrow');
56+
5557
class Histogram {
56-
constructor() {
57-
throw new ERR_ILLEGAL_CONSTRUCTOR();
58+
constructor(skipThrowSymbol = undefined) {
59+
if (skipThrowSymbol !== kSkipThrow) {
60+
throw new ERR_ILLEGAL_CONSTRUCTOR();
61+
}
5862
}
5963

6064
[kInspect](depth, options) {
@@ -242,7 +246,7 @@ class Histogram {
242246
const handle = this[kHandle];
243247
return {
244248
data: { handle },
245-
deserializeInfo: 'internal/histogram:internalHistogram',
249+
deserializeInfo: 'internal/histogram:ClonedHistogram',
246250
};
247251
}
248252

@@ -264,8 +268,12 @@ class Histogram {
264268
}
265269

266270
class RecordableHistogram extends Histogram {
267-
constructor() {
268-
throw new ERR_ILLEGAL_CONSTRUCTOR();
271+
constructor(skipThrowSymbol = undefined) {
272+
if (skipThrowSymbol !== kSkipThrow) {
273+
throw new ERR_ILLEGAL_CONSTRUCTOR();
274+
}
275+
276+
super(skipThrowSymbol);
269277
}
270278

271279
/**
@@ -309,7 +317,7 @@ class RecordableHistogram extends Histogram {
309317
const handle = this[kHandle];
310318
return {
311319
data: { handle },
312-
deserializeInfo: 'internal/histogram:internalRecordableHistogram',
320+
deserializeInfo: 'internal/histogram:ClonedRecordableHistogram',
313321
};
314322
}
315323

@@ -318,24 +326,32 @@ class RecordableHistogram extends Histogram {
318326
}
319327
}
320328

321-
function internalHistogram(handle) {
329+
function ClonedHistogram(handle) {
322330
return makeTransferable(ReflectConstruct(
323331
function() {
324332
this[kHandle] = handle;
325333
this[kMap] = new SafeMap();
326334
}, [], Histogram));
327335
}
328-
internalHistogram.prototype[kDeserialize] = () => {};
329336

330-
function internalRecordableHistogram(handle) {
331-
return makeTransferable(ReflectConstruct(
332-
function() {
333-
this[kHandle] = handle;
334-
this[kMap] = new SafeMap();
335-
this[kRecordable] = true;
336-
}, [], RecordableHistogram));
337+
ClonedHistogram.prototype[kDeserialize] = () => { };
338+
339+
function ClonedRecordableHistogram(handle) {
340+
const histogram = new RecordableHistogram(kSkipThrow);
341+
342+
histogram[kRecordable] = true;
343+
histogram[kMap] = new SafeMap();
344+
histogram[kHandle] = handle;
345+
histogram.constructor = RecordableHistogram;
346+
347+
return makeTransferable(histogram);
348+
}
349+
350+
ClonedRecordableHistogram.prototype[kDeserialize] = () => { };
351+
352+
function createRecordableHistogram(handle) {
353+
return new ClonedRecordableHistogram(handle);
337354
}
338-
internalRecordableHistogram.prototype[kDeserialize] = () => {};
339355

340356
/**
341357
* @param {{
@@ -361,14 +377,14 @@ function createHistogram(options = kEmptyObject) {
361377
throw new ERR_INVALID_ARG_VALUE.RangeError('options.highest', highest);
362378
}
363379
validateInteger(figures, 'options.figures', 1, 5);
364-
return internalRecordableHistogram(new _Histogram(lowest, highest, figures));
380+
return createRecordableHistogram(new _Histogram(lowest, highest, figures));
365381
}
366382

367383
module.exports = {
368384
Histogram,
369385
RecordableHistogram,
370-
internalHistogram,
371-
internalRecordableHistogram,
386+
ClonedHistogram,
387+
ClonedRecordableHistogram,
372388
isHistogram,
373389
kDestroy,
374390
kHandle,

0 commit comments

Comments
 (0)
Please sign in to comment.