diff --git a/src/env.cc b/src/env.cc index 65467587ffcdd8..f25fd0aa1a128e 100644 --- a/src/env.cc +++ b/src/env.cc @@ -352,7 +352,8 @@ Environment::Environment(IsolateData* isolate_data, stream_base_state_(isolate_, StreamBase::kNumStreamBaseStateFields, MAYBE_FIELD_PTR(env_info, stream_base_state)), - environment_start_time_(PERFORMANCE_NOW()), + time_origin_(PERFORMANCE_NOW()), + time_origin_timestamp_(GetCurrentTimeInMicroseconds()), flags_(flags), thread_id_(thread_id.id == static_cast(-1) ? AllocateEnvironmentThreadId().id @@ -455,7 +456,7 @@ void Environment::InitializeMainContext(Local context, should_abort_on_uncaught_toggle_[0] = 1; performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT, - environment_start_time_); + time_origin_); performance_state_->Mark(performance::NODE_PERFORMANCE_MILESTONE_NODE_START, per_process::node_start_time); diff --git a/src/env.h b/src/env.h index 52bfaa3db8d46c..c1a5f04e863988 100644 --- a/src/env.h +++ b/src/env.h @@ -1380,6 +1380,9 @@ class Environment : public MemoryRetainer { inline HandleWrapQueue* handle_wrap_queue() { return &handle_wrap_queue_; } inline ReqWrapQueue* req_wrap_queue() { return &req_wrap_queue_; } + inline uint64_t time_origin() { return time_origin_; } + inline double time_origin_timestamp() { return time_origin_timestamp_; } + inline bool EmitProcessEnvWarning() { bool current_value = emit_env_nonstring_warning_; emit_env_nonstring_warning_ = false; @@ -1568,7 +1571,10 @@ class Environment : public MemoryRetainer { AliasedInt32Array stream_base_state_; - uint64_t environment_start_time_; + // https://w3c.github.io/hr-time/#dfn-time-origin + uint64_t time_origin_; + // https://w3c.github.io/hr-time/#dfn-get-time-origin-timestamp + double time_origin_timestamp_; std::unique_ptr performance_state_; bool has_run_bootstrapping_code_ = false; diff --git a/src/node_http2.cc b/src/node_http2.cc index 4c180c539a7d5e..f5723821f3f48c 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -640,7 +640,7 @@ void Http2Stream::EmitStatistics() { std::unique_ptr entry = std::make_unique( "Http2Stream", - start - (node::performance::timeOrigin / 1e6), + start - (env()->time_origin() / 1e6), duration, statistics_); @@ -660,7 +660,7 @@ void Http2Session::EmitStatistics() { std::unique_ptr entry = std::make_unique( "Http2Session", - start - (node::performance::timeOrigin / 1e6), + start - (env()->time_origin() / 1e6), duration, statistics_); diff --git a/src/node_perf.cc b/src/node_perf.cc index 253f72157e8a7b..6b61b2083275cd 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -35,11 +35,9 @@ using v8::Value; // Microseconds in a millisecond, as a float. #define MICROS_PER_MILLIS 1e3 +// Nanoseconds in a millisecond, as a float. +#define NANOS_PER_MILLIS 1e6 -// https://w3c.github.io/hr-time/#dfn-time-origin -const uint64_t timeOrigin = PERFORMANCE_NOW(); -// https://w3c.github.io/hr-time/#dfn-time-origin-timestamp -const double timeOriginTimestamp = GetCurrentTimeInMicroseconds(); uint64_t performance_v8_start; PerformanceState::PerformanceState(Isolate* isolate, @@ -160,9 +158,9 @@ void MarkGarbageCollectionEnd( return; double start_time = - (state->performance_last_gc_start_mark - timeOrigin) / 1e6; + (state->performance_last_gc_start_mark - env->time_origin()) / NANOS_PER_MILLIS; double duration = - (PERFORMANCE_NOW() / 1e6) - (state->performance_last_gc_start_mark / 1e6); + (PERFORMANCE_NOW() / NANOS_PER_MILLIS) - (state->performance_last_gc_start_mark / NANOS_PER_MILLIS); std::unique_ptr entry = std::make_unique( @@ -257,12 +255,14 @@ void CreateELDHistogram(const FunctionCallbackInfo& args) { } void GetTimeOrigin(const FunctionCallbackInfo& args) { - args.GetReturnValue().Set(Number::New(args.GetIsolate(), timeOrigin / 1e6)); + Environment* env = Environment::GetCurrent(args); + args.GetReturnValue().Set(Number::New(args.GetIsolate(), env->time_origin() / 1e6)); } void GetTimeOriginTimeStamp(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); args.GetReturnValue().Set( - Number::New(args.GetIsolate(), timeOriginTimestamp / MICROS_PER_MILLIS)); + Number::New(args.GetIsolate(), env->time_origin_timestamp() / MICROS_PER_MILLIS)); } void Initialize(Local target, diff --git a/src/node_perf.h b/src/node_perf.h index b1a991713866ab..3e994ce5a63b7d 100644 --- a/src/node_perf.h +++ b/src/node_perf.h @@ -21,8 +21,6 @@ class ExternalReferenceRegistry; namespace performance { -extern const uint64_t timeOrigin; - inline const char* GetPerformanceMilestoneName( PerformanceMilestone milestone) { switch (milestone) { diff --git a/src/node_worker.cc b/src/node_worker.cc index 8385bc96231257..5e633ee98b2d48 100644 --- a/src/node_worker.cc +++ b/src/node_worker.cc @@ -817,7 +817,7 @@ void Worker::LoopStartTime(const FunctionCallbackInfo& args) { node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START]; CHECK_GE(loop_start_time, 0); args.GetReturnValue().Set( - (loop_start_time - node::performance::timeOrigin) / 1e6); + (loop_start_time - w->env_->time_origin()) / 1e6); } namespace { diff --git a/test/parallel/test-perf-hooks-worker-timeorigin.js b/test/parallel/test-perf-hooks-worker-timeorigin.js new file mode 100644 index 00000000000000..ad67a16ab0c93b --- /dev/null +++ b/test/parallel/test-perf-hooks-worker-timeorigin.js @@ -0,0 +1,20 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { Worker } = require('worker_threads'); + +const w = new Worker(` +require('worker_threads').parentPort.postMessage(performance.timeOrigin); +`, { eval: true }) + +w.on('message', common.mustCall(timeOrigin => { + // Worker is created after this main context, it's + // `performance.timeOrigin` must be greater than this + // main context's. + assert.ok(timeOrigin > performance.timeOrigin); +})); + +w.on('exit', common.mustCall(code => { + assert.strictEqual(code, 0); +}));