mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
perf_hooks: performance milestone time origin timestamp improvement
PR-URL: https://github.com/nodejs/node/pull/51713 Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br> Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
8e7da60468
commit
f4af4b111c
6 changed files with 77 additions and 27 deletions
45
benchmark/perf_hooks/time-origin.js
Normal file
45
benchmark/perf_hooks/time-origin.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const common = require('../common.js');
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
n: [1e6],
|
||||||
|
method: ['timeOrigin', 'toJSON'],
|
||||||
|
});
|
||||||
|
|
||||||
|
function main({ method, n }) {
|
||||||
|
switch (method) {
|
||||||
|
case 'timeOrigin':
|
||||||
|
benchTimeOrigin(n);
|
||||||
|
break;
|
||||||
|
case 'toJSON':
|
||||||
|
benchToJSON(n);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported method ${method}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function benchTimeOrigin(n) {
|
||||||
|
const arr = [];
|
||||||
|
for (let i = 0; i < n; ++i) {
|
||||||
|
arr.push(performance.timeOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
arr[i] = performance.timeOrigin;
|
||||||
|
}
|
||||||
|
bench.end(n);
|
||||||
|
|
||||||
|
assert.strictEqual(arr.length, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
function benchToJSON(n) {
|
||||||
|
bench.start();
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
performance.toJSON();
|
||||||
|
}
|
||||||
|
bench.end(n);
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ const {
|
||||||
defineEventHandler,
|
defineEventHandler,
|
||||||
} = require('internal/event_target');
|
} = require('internal/event_target');
|
||||||
|
|
||||||
const { now } = require('internal/perf/utils');
|
const { now, getTimeOriginTimestamp } = require('internal/perf/utils');
|
||||||
|
|
||||||
const { markResourceTiming } = require('internal/perf/resource_timing');
|
const { markResourceTiming } = require('internal/perf/resource_timing');
|
||||||
|
|
||||||
|
@ -46,10 +46,6 @@ const { inspect } = require('util');
|
||||||
const { validateInternalField } = require('internal/validators');
|
const { validateInternalField } = require('internal/validators');
|
||||||
const { convertToInt } = require('internal/webidl');
|
const { convertToInt } = require('internal/webidl');
|
||||||
|
|
||||||
const {
|
|
||||||
getTimeOriginTimestamp,
|
|
||||||
} = internalBinding('performance');
|
|
||||||
|
|
||||||
const kPerformanceBrand = Symbol('performance');
|
const kPerformanceBrand = Symbol('performance');
|
||||||
|
|
||||||
class Performance extends EventTarget {
|
class Performance extends EventTarget {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
const {
|
const {
|
||||||
constants: {
|
constants: {
|
||||||
NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN,
|
NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN,
|
||||||
|
NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN_TIMESTAMP,
|
||||||
},
|
},
|
||||||
milestones,
|
milestones,
|
||||||
now,
|
now,
|
||||||
|
@ -22,7 +23,12 @@ function getMilestoneTimestamp(milestoneIdx) {
|
||||||
return ns / 1e6 - getTimeOrigin();
|
return ns / 1e6 - getTimeOrigin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTimeOriginTimestamp() {
|
||||||
|
return milestones[NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN_TIMESTAMP] / 1e3;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
now,
|
now,
|
||||||
getMilestoneTimestamp,
|
getMilestoneTimestamp,
|
||||||
|
getTimeOriginTimestamp,
|
||||||
};
|
};
|
||||||
|
|
|
@ -880,7 +880,10 @@ Environment::Environment(IsolateData* isolate_data,
|
||||||
destroy_async_id_list_.reserve(512);
|
destroy_async_id_list_.reserve(512);
|
||||||
|
|
||||||
performance_state_ = std::make_unique<performance::PerformanceState>(
|
performance_state_ = std::make_unique<performance::PerformanceState>(
|
||||||
isolate, time_origin_, MAYBE_FIELD_PTR(env_info, performance_state));
|
isolate,
|
||||||
|
time_origin_,
|
||||||
|
time_origin_timestamp_,
|
||||||
|
MAYBE_FIELD_PTR(env_info, performance_state));
|
||||||
|
|
||||||
if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
|
if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(
|
||||||
TRACING_CATEGORY_NODE1(environment)) != 0) {
|
TRACING_CATEGORY_NODE1(environment)) != 0) {
|
||||||
|
@ -1837,7 +1840,7 @@ void Environment::DeserializeProperties(const EnvSerializeInfo* info) {
|
||||||
immediate_info_.Deserialize(ctx);
|
immediate_info_.Deserialize(ctx);
|
||||||
timeout_info_.Deserialize(ctx);
|
timeout_info_.Deserialize(ctx);
|
||||||
tick_info_.Deserialize(ctx);
|
tick_info_.Deserialize(ctx);
|
||||||
performance_state_->Deserialize(ctx, time_origin_);
|
performance_state_->Deserialize(ctx, time_origin_, time_origin_timestamp_);
|
||||||
exit_info_.Deserialize(ctx);
|
exit_info_.Deserialize(ctx);
|
||||||
stream_base_state_.Deserialize(ctx);
|
stream_base_state_.Deserialize(ctx);
|
||||||
should_abort_on_uncaught_toggle_.Deserialize(ctx);
|
should_abort_on_uncaught_toggle_.Deserialize(ctx);
|
||||||
|
|
|
@ -24,7 +24,6 @@ using v8::Integer;
|
||||||
using v8::Isolate;
|
using v8::Isolate;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
using v8::MaybeLocal;
|
using v8::MaybeLocal;
|
||||||
using v8::Number;
|
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
using v8::ObjectTemplate;
|
using v8::ObjectTemplate;
|
||||||
using v8::PropertyAttribute;
|
using v8::PropertyAttribute;
|
||||||
|
@ -43,6 +42,7 @@ uint64_t performance_v8_start;
|
||||||
|
|
||||||
PerformanceState::PerformanceState(Isolate* isolate,
|
PerformanceState::PerformanceState(Isolate* isolate,
|
||||||
uint64_t time_origin,
|
uint64_t time_origin,
|
||||||
|
double time_origin_timestamp,
|
||||||
const PerformanceState::SerializeInfo* info)
|
const PerformanceState::SerializeInfo* info)
|
||||||
: root(isolate,
|
: root(isolate,
|
||||||
sizeof(performance_state_internal),
|
sizeof(performance_state_internal),
|
||||||
|
@ -63,7 +63,7 @@ PerformanceState::PerformanceState(Isolate* isolate,
|
||||||
// For deserialized performance states, we will do the
|
// For deserialized performance states, we will do the
|
||||||
// initialization in the deserialize callback.
|
// initialization in the deserialize callback.
|
||||||
ResetMilestones();
|
ResetMilestones();
|
||||||
Initialize(time_origin);
|
Initialize(time_origin, time_origin_timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,23 +86,27 @@ PerformanceState::SerializeInfo PerformanceState::Serialize(
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceState::Initialize(uint64_t time_origin) {
|
void PerformanceState::Initialize(uint64_t time_origin,
|
||||||
// We are only reusing the milestone array to store the time origin, so do
|
double time_origin_timestamp) {
|
||||||
// not use the Mark() method. The time origin milestone is not exposed
|
// We are only reusing the milestone array to store the time origin
|
||||||
// to user land.
|
// and time origin timestamp, so do not use the Mark() method.
|
||||||
|
// The time origin milestone is not exposed to user land.
|
||||||
this->milestones[NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN] =
|
this->milestones[NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN] =
|
||||||
static_cast<double>(time_origin);
|
static_cast<double>(time_origin);
|
||||||
|
this->milestones[NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN_TIMESTAMP] =
|
||||||
|
time_origin_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceState::Deserialize(v8::Local<v8::Context> context,
|
void PerformanceState::Deserialize(v8::Local<v8::Context> context,
|
||||||
uint64_t time_origin) {
|
uint64_t time_origin,
|
||||||
|
double time_origin_timestamp) {
|
||||||
// Resets the pointers.
|
// Resets the pointers.
|
||||||
root.Deserialize(context);
|
root.Deserialize(context);
|
||||||
milestones.Deserialize(context);
|
milestones.Deserialize(context);
|
||||||
observers.Deserialize(context);
|
observers.Deserialize(context);
|
||||||
|
|
||||||
// Re-initialize the time origin i.e. the process start time.
|
// Re-initialize the time origin and timestamp i.e. the process start time.
|
||||||
Initialize(time_origin);
|
Initialize(time_origin, time_origin_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& o,
|
std::ostream& operator<<(std::ostream& o,
|
||||||
|
@ -254,7 +258,7 @@ void Notify(const FunctionCallbackInfo<Value>& args) {
|
||||||
void LoopIdleTime(const FunctionCallbackInfo<Value>& args) {
|
void LoopIdleTime(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
uint64_t idle_time = uv_metrics_idle_time(env->event_loop());
|
uint64_t idle_time = uv_metrics_idle_time(env->event_loop());
|
||||||
args.GetReturnValue().Set(1.0 * idle_time / 1e6);
|
args.GetReturnValue().Set(1.0 * idle_time / NANOS_PER_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateELDHistogram(const FunctionCallbackInfo<Value>& args) {
|
void CreateELDHistogram(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
@ -278,12 +282,6 @@ void CreateELDHistogram(const FunctionCallbackInfo<Value>& args) {
|
||||||
args.GetReturnValue().Set(histogram->object());
|
args.GetReturnValue().Set(histogram->object());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetTimeOriginTimeStamp(const FunctionCallbackInfo<Value>& args) {
|
|
||||||
Environment* env = Environment::GetCurrent(args);
|
|
||||||
args.GetReturnValue().Set(Number::New(
|
|
||||||
args.GetIsolate(), env->time_origin_timestamp() / MICROS_PER_MILLIS));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
|
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
|
||||||
Realm* realm = Realm::GetCurrent(args);
|
Realm* realm = Realm::GetCurrent(args);
|
||||||
CHECK_EQ(realm->kind(), Realm::Kind::kPrincipal);
|
CHECK_EQ(realm->kind(), Realm::Kind::kPrincipal);
|
||||||
|
@ -324,7 +322,6 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
|
||||||
RemoveGarbageCollectionTracking);
|
RemoveGarbageCollectionTracking);
|
||||||
SetMethod(isolate, target, "notify", Notify);
|
SetMethod(isolate, target, "notify", Notify);
|
||||||
SetMethod(isolate, target, "loopIdleTime", LoopIdleTime);
|
SetMethod(isolate, target, "loopIdleTime", LoopIdleTime);
|
||||||
SetMethod(isolate, target, "getTimeOriginTimestamp", GetTimeOriginTimeStamp);
|
|
||||||
SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram);
|
SetMethod(isolate, target, "createELDHistogram", CreateELDHistogram);
|
||||||
SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete);
|
SetMethod(isolate, target, "markBootstrapComplete", MarkBootstrapComplete);
|
||||||
SetFastMethodNoSideEffect(
|
SetFastMethodNoSideEffect(
|
||||||
|
@ -391,7 +388,6 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||||
registry->Register(RemoveGarbageCollectionTracking);
|
registry->Register(RemoveGarbageCollectionTracking);
|
||||||
registry->Register(Notify);
|
registry->Register(Notify);
|
||||||
registry->Register(LoopIdleTime);
|
registry->Register(LoopIdleTime);
|
||||||
registry->Register(GetTimeOriginTimeStamp);
|
|
||||||
registry->Register(CreateELDHistogram);
|
registry->Register(CreateELDHistogram);
|
||||||
registry->Register(MarkBootstrapComplete);
|
registry->Register(MarkBootstrapComplete);
|
||||||
registry->Register(SlowPerformanceNow);
|
registry->Register(SlowPerformanceNow);
|
||||||
|
|
|
@ -25,6 +25,7 @@ extern const double performance_process_start_timestamp;
|
||||||
extern uint64_t performance_v8_start;
|
extern uint64_t performance_v8_start;
|
||||||
|
|
||||||
#define NODE_PERFORMANCE_MILESTONES(V) \
|
#define NODE_PERFORMANCE_MILESTONES(V) \
|
||||||
|
V(TIME_ORIGIN_TIMESTAMP, "timeOriginTimestamp") \
|
||||||
V(TIME_ORIGIN, "timeOrigin") \
|
V(TIME_ORIGIN, "timeOrigin") \
|
||||||
V(ENVIRONMENT, "environment") \
|
V(ENVIRONMENT, "environment") \
|
||||||
V(NODE_START, "nodeStart") \
|
V(NODE_START, "nodeStart") \
|
||||||
|
@ -64,10 +65,13 @@ class PerformanceState {
|
||||||
|
|
||||||
explicit PerformanceState(v8::Isolate* isolate,
|
explicit PerformanceState(v8::Isolate* isolate,
|
||||||
uint64_t time_origin,
|
uint64_t time_origin,
|
||||||
|
double time_origin_timestamp,
|
||||||
const SerializeInfo* info);
|
const SerializeInfo* info);
|
||||||
SerializeInfo Serialize(v8::Local<v8::Context> context,
|
SerializeInfo Serialize(v8::Local<v8::Context> context,
|
||||||
v8::SnapshotCreator* creator);
|
v8::SnapshotCreator* creator);
|
||||||
void Deserialize(v8::Local<v8::Context> context, uint64_t time_origin);
|
void Deserialize(v8::Local<v8::Context> context,
|
||||||
|
uint64_t time_origin,
|
||||||
|
double time_origin_timestamp);
|
||||||
friend std::ostream& operator<<(std::ostream& o, const SerializeInfo& i);
|
friend std::ostream& operator<<(std::ostream& o, const SerializeInfo& i);
|
||||||
|
|
||||||
AliasedUint8Array root;
|
AliasedUint8Array root;
|
||||||
|
@ -81,7 +85,7 @@ class PerformanceState {
|
||||||
uint64_t ts = PERFORMANCE_NOW());
|
uint64_t ts = PERFORMANCE_NOW());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Initialize(uint64_t time_origin);
|
void Initialize(uint64_t time_origin, double time_origin_timestamp);
|
||||||
void ResetMilestones();
|
void ResetMilestones();
|
||||||
struct performance_state_internal {
|
struct performance_state_internal {
|
||||||
// doubles first so that they are always sizeof(double)-aligned
|
// doubles first so that they are always sizeof(double)-aligned
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue