From a9031e7d9ea65ab95f38f5fedf8095e43b7c4d85 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sat, 18 Nov 2023 00:59:26 +0100 Subject: [PATCH] perf_hooks: implement performance.now() with fast API calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/50492 Reviewed-By: Vinícius Lourenço Claro Cardoso Reviewed-By: Yagiz Nizipli Reviewed-By: Bryan English Reviewed-By: Chengzhong Wu Reviewed-By: Benjamin Gruenbaum Reviewed-By: Stephen Belanger --- benchmark/perf_hooks/now.js | 23 +++++++++++++++++++++++ lib/internal/perf/utils.js | 7 +------ src/node_external_reference.h | 3 +++ src/node_perf.cc | 21 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 benchmark/perf_hooks/now.js diff --git a/benchmark/perf_hooks/now.js b/benchmark/perf_hooks/now.js new file mode 100644 index 00000000000000..7132196c430125 --- /dev/null +++ b/benchmark/perf_hooks/now.js @@ -0,0 +1,23 @@ +'use strict'; + +const assert = require('assert'); +const common = require('../common.js'); + +const bench = common.createBenchmark(main, { + n: [1e6], +}); + +function main({ n }) { + const arr = []; + for (let i = 0; i < n; ++i) { + arr.push(performance.now()); + } + + bench.start(); + for (let i = 0; i < n; i++) { + arr[i] = performance.now(); + } + bench.end(n); + + assert.strictEqual(arr.length, n); +} diff --git a/lib/internal/perf/utils.js b/lib/internal/perf/utils.js index a0b7955c70481c..bbc1c996e318f8 100644 --- a/lib/internal/perf/utils.js +++ b/lib/internal/perf/utils.js @@ -5,6 +5,7 @@ const { NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN, }, milestones, + now, } = internalBinding('performance'); function getTimeOrigin() { @@ -13,12 +14,6 @@ function getTimeOrigin() { return milestones[NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN] / 1e6; } -// Returns the time relative to the process start time in milliseconds. -function now() { - const hr = process.hrtime(); - return (hr[0] * 1000 + hr[1] / 1e6) - getTimeOrigin(); -} - // Returns the milestone relative to the process start time in milliseconds. function getMilestoneTimestamp(milestoneIdx) { const ns = milestones[milestoneIdx]; diff --git a/src/node_external_reference.h b/src/node_external_reference.h index a647967077967e..f15c97c03d2e9d 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -15,6 +15,8 @@ using CFunctionCallbackWithOneByteString = using CFunctionCallback = void (*)(v8::Local receiver); using CFunctionCallbackReturnDouble = double (*)(v8::Local receiver); +using CFunctionCallbackValueReturnDouble = + double (*)(v8::Local receiver); using CFunctionCallbackWithInt64 = void (*)(v8::Local receiver, int64_t); using CFunctionCallbackWithBool = void (*)(v8::Local receiver, @@ -38,6 +40,7 @@ class ExternalReferenceRegistry { V(CFunctionCallback) \ V(CFunctionCallbackWithOneByteString) \ V(CFunctionCallbackReturnDouble) \ + V(CFunctionCallbackValueReturnDouble) \ V(CFunctionCallbackWithInt64) \ V(CFunctionCallbackWithBool) \ V(CFunctionCallbackWithString) \ diff --git a/src/node_perf.cc b/src/node_perf.cc index 360cc8bf673073..603af57b2639b2 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -291,6 +291,22 @@ void MarkBootstrapComplete(const FunctionCallbackInfo& args) { performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE); } +static double PerformanceNowImpl() { + return static_cast(uv_hrtime() - performance_process_start) / + NANOS_PER_MILLIS; +} + +static double FastPerformanceNow(v8::Local receiver) { + return PerformanceNowImpl(); +} + +static void SlowPerformanceNow(const FunctionCallbackInfo& args) { + args.GetReturnValue().Set(PerformanceNowImpl()); +} + +static v8::CFunction fast_performance_now( + v8::CFunction::Make(FastPerformanceNow)); + static void CreatePerIsolateProperties(IsolateData* isolate_data, Local target) { Isolate* isolate = isolate_data->isolate(); @@ -311,6 +327,8 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data, SetMethod(isolate, target, "getTimeOriginTimestamp", GetTimeOriginTimeStamp); SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram); SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete); + SetFastMethodNoSideEffect( + isolate, target, "now", SlowPerformanceNow, &fast_performance_now); } void CreatePerContextProperties(Local target, @@ -376,6 +394,9 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { registry->Register(GetTimeOriginTimeStamp); registry->Register(CreateELDHistogram); registry->Register(MarkBootstrapComplete); + registry->Register(SlowPerformanceNow); + registry->Register(FastPerformanceNow); + registry->Register(fast_performance_now.GetTypeInfo()); HistogramBase::RegisterExternalReferences(registry); IntervalHistogram::RegisterExternalReferences(registry); }