From 402067a1b91235abf5387a55c7fbc82cafee4091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Louren=C3=A7o?= Date: Sun, 1 Oct 2023 21:26:56 -0300 Subject: [PATCH 1/3] perf_hooks: reducing overhead of performance observer entry list --- benchmark/perf_hooks/performance-observer.js | 49 ++++++++++++++++++++ lib/internal/perf/observe.js | 23 +++++---- 2 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 benchmark/perf_hooks/performance-observer.js diff --git a/benchmark/perf_hooks/performance-observer.js b/benchmark/perf_hooks/performance-observer.js new file mode 100644 index 00000000000000..a0bcca452c1130 --- /dev/null +++ b/benchmark/perf_hooks/performance-observer.js @@ -0,0 +1,49 @@ +'use strict'; + +const assert = require('assert'); +const common = require('../common.js'); + +const { + PerformanceObserver, + performance, +} = require('perf_hooks'); + +function randomFn() { + return Math.random(); +} + +const bench = common.createBenchmark(main, { + n: [1e5], + pending: [1, 10], +}, { + options: ['--expose-internals'] +}); + +let _result; + +function fillQueue(timerfied, pending) { + for (let i = 0; i < pending; i++) { + _result = timerfied(); + } + // Avoid V8 deadcode (elimination) + assert.ok(_result); +} + +function main({ n, pending }) { + const timerfied = performance.timerify(randomFn); + + let count = 0; + const obs = new PerformanceObserver((entries) => { + count += entries.getEntries().length; + + if (count >= n) { + bench.end(count); + } else { + fillQueue(timerfied, pending); + } + }); + obs.observe({ entryTypes: ['function'], buffered: true }); + + bench.start(); + fillQueue(timerfied, pending); +} diff --git a/lib/internal/perf/observe.js b/lib/internal/perf/observe.js index b97ae08402260a..a1eb3e0c5dc055 100644 --- a/lib/internal/perf/observe.js +++ b/lib/internal/perf/observe.js @@ -171,9 +171,18 @@ function maybeIncrementObserverCount(type) { } } +const kSkipThrow = Symbol('kSkipThrow'); +const performanceObserverSorter = (first, second) => { + return first.startTime - second.startTime; +}; + class PerformanceObserverEntryList { - constructor() { - throw new ERR_ILLEGAL_CONSTRUCTOR(); + constructor(skipThrowSymbol = undefined, entries = []) { + if (skipThrowSymbol !== kSkipThrow) { + throw new ERR_ILLEGAL_CONSTRUCTOR(); + } + + this[kBuffer] = ArrayPrototypeSort(entries, performanceObserverSorter); } getEntries() { @@ -233,11 +242,7 @@ ObjectDefineProperties(PerformanceObserverEntryList.prototype, { }); function createPerformanceObserverEntryList(entries) { - return ReflectConstruct(function PerformanceObserverEntryList() { - this[kBuffer] = ArrayPrototypeSort(entries, (first, second) => { - return first.startTime - second.startTime; - }); - }, [], PerformanceObserverEntryList); + return new PerformanceObserverEntryList(kSkipThrow, entries); } class PerformanceObserver { @@ -523,9 +528,7 @@ function filterBufferMapByNameAndType(name, type) { bufferList = ArrayPrototypeSlice(bufferList); } - return ArrayPrototypeSort(bufferList, (first, second) => { - return first.startTime - second.startTime; - }); + return ArrayPrototypeSort(bufferList, performanceObserverSorter); } function observerCallback(name, type, startTime, duration, details) { From 72b0d05080907a2949c25ca3954e09f864129a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Louren=C3=A7o?= Date: Sun, 1 Oct 2023 21:44:29 -0300 Subject: [PATCH 2/3] fixup! perf_hooks: reducing overhead of performance observer entry list --- benchmark/perf_hooks/performance-observer.js | 2 +- lib/internal/perf/observe.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/benchmark/perf_hooks/performance-observer.js b/benchmark/perf_hooks/performance-observer.js index a0bcca452c1130..42a94932860c38 100644 --- a/benchmark/perf_hooks/performance-observer.js +++ b/benchmark/perf_hooks/performance-observer.js @@ -16,7 +16,7 @@ const bench = common.createBenchmark(main, { n: [1e5], pending: [1, 10], }, { - options: ['--expose-internals'] + options: ['--expose-internals'], }); let _result; diff --git a/lib/internal/perf/observe.js b/lib/internal/perf/observe.js index a1eb3e0c5dc055..fe0b6d55efcb84 100644 --- a/lib/internal/perf/observe.js +++ b/lib/internal/perf/observe.js @@ -15,7 +15,6 @@ const { ObjectDefineProperties, ObjectFreeze, ObjectKeys, - ReflectConstruct, SafeMap, SafeSet, Symbol, From 8a2a5337483a00ba85b46bebe7bd06993cb3d594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Louren=C3=A7o?= Date: Sun, 1 Oct 2023 22:05:50 -0300 Subject: [PATCH 3/3] fixup! perf_hooks: reducing overhead of performance observer entry list --- lib/internal/perf/observe.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/internal/perf/observe.js b/lib/internal/perf/observe.js index fe0b6d55efcb84..244d01f541d886 100644 --- a/lib/internal/perf/observe.js +++ b/lib/internal/perf/observe.js @@ -240,10 +240,6 @@ ObjectDefineProperties(PerformanceObserverEntryList.prototype, { }, }); -function createPerformanceObserverEntryList(entries) { - return new PerformanceObserverEntryList(kSkipThrow, entries); -} - class PerformanceObserver { #buffer = []; #entryTypes = new SafeSet(); @@ -353,8 +349,9 @@ class PerformanceObserver { } [kDispatch]() { - this.#callback(createPerformanceObserverEntryList(this.takeRecords()), - this); + const entryList = new PerformanceObserverEntryList(kSkipThrow, this.takeRecords()); + + this.#callback(entryList, this); } [kInspect](depth, options) {