perf_hooks: refactor internals
Refactor and simplify the perf_hooks native internals. PR-URL: https://github.com/nodejs/node/pull/17822 Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
6c0da34905
commit
9e5ccf0313
259
src/node_perf.cc
259
src/node_perf.cc
@ -17,9 +17,8 @@ using v8::Integer;
|
|||||||
using v8::Isolate;
|
using v8::Isolate;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
using v8::Name;
|
using v8::Name;
|
||||||
|
using v8::Number;
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
using v8::ObjectTemplate;
|
|
||||||
using v8::Signature;
|
|
||||||
using v8::String;
|
using v8::String;
|
||||||
using v8::Value;
|
using v8::Value;
|
||||||
|
|
||||||
@ -30,37 +29,78 @@ uint64_t performance_v8_start;
|
|||||||
uint64_t performance_last_gc_start_mark_ = 0;
|
uint64_t performance_last_gc_start_mark_ = 0;
|
||||||
v8::GCType performance_last_gc_type_ = v8::GCType::kGCTypeAll;
|
v8::GCType performance_last_gc_type_ = v8::GCType::kGCTypeAll;
|
||||||
|
|
||||||
|
// Initialize the performance entry object properties
|
||||||
|
inline void InitObject(const PerformanceEntry& entry, Local<Object> obj) {
|
||||||
|
Environment* env = entry.env();
|
||||||
|
Isolate* isolate = env->isolate();
|
||||||
|
Local<Context> context = env->context();
|
||||||
|
v8::PropertyAttribute attr =
|
||||||
|
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
|
||||||
|
obj->DefineOwnProperty(context,
|
||||||
|
env->name_string(),
|
||||||
|
String::NewFromUtf8(isolate,
|
||||||
|
entry.name().c_str(),
|
||||||
|
String::kNormalString),
|
||||||
|
attr).FromJust();
|
||||||
|
obj->DefineOwnProperty(context,
|
||||||
|
FIXED_ONE_BYTE_STRING(isolate, "entryType"),
|
||||||
|
String::NewFromUtf8(isolate,
|
||||||
|
entry.type().c_str(),
|
||||||
|
String::kNormalString),
|
||||||
|
attr).FromJust();
|
||||||
|
obj->DefineOwnProperty(context,
|
||||||
|
FIXED_ONE_BYTE_STRING(isolate, "startTime"),
|
||||||
|
Number::New(isolate, entry.startTime()),
|
||||||
|
attr).FromJust();
|
||||||
|
obj->DefineOwnProperty(context,
|
||||||
|
FIXED_ONE_BYTE_STRING(isolate, "duration"),
|
||||||
|
Number::New(isolate, entry.duration()),
|
||||||
|
attr).FromJust();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new PerformanceEntry object
|
||||||
|
const Local<Object> PerformanceEntry::ToObject() const {
|
||||||
|
Local<Object> obj =
|
||||||
|
env_->performance_entry_template()
|
||||||
|
->NewInstance(env_->context()).ToLocalChecked();
|
||||||
|
InitObject(*this, obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow creating a PerformanceEntry object from JavaScript
|
||||||
void PerformanceEntry::New(const FunctionCallbackInfo<Value>& args) {
|
void PerformanceEntry::New(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
Isolate* isolate = env->isolate();
|
Isolate* isolate = env->isolate();
|
||||||
Utf8Value name(isolate, args[0]);
|
Utf8Value name(isolate, args[0]);
|
||||||
Utf8Value type(isolate, args[1]);
|
Utf8Value type(isolate, args[1]);
|
||||||
uint64_t now = PERFORMANCE_NOW();
|
uint64_t now = PERFORMANCE_NOW();
|
||||||
new PerformanceEntry(env, args.This(), *name, *type, now, now);
|
PerformanceEntry entry(env, *name, *type, now, now);
|
||||||
|
Local<Object> obj = args.This();
|
||||||
|
InitObject(entry, obj);
|
||||||
|
PerformanceEntry::Notify(env, entry.kind(), obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceEntry::NotifyObservers(Environment* env,
|
// Pass the PerformanceEntry object to the PerformanceObservers
|
||||||
PerformanceEntry* entry) {
|
inline void PerformanceEntry::Notify(Environment* env,
|
||||||
|
PerformanceEntryType type,
|
||||||
|
Local<Value> object) {
|
||||||
|
Context::Scope scope(env->context());
|
||||||
uint32_t* observers = env->performance_state()->observers;
|
uint32_t* observers = env->performance_state()->observers;
|
||||||
PerformanceEntryType type = ToPerformanceEntryTypeEnum(entry->type().c_str());
|
if (observers != nullptr &&
|
||||||
if (observers == nullptr ||
|
type != NODE_PERFORMANCE_ENTRY_TYPE_INVALID &&
|
||||||
type == NODE_PERFORMANCE_ENTRY_TYPE_INVALID ||
|
observers[type]) {
|
||||||
!observers[type]) {
|
node::MakeCallback(env->isolate(),
|
||||||
return;
|
env->process_object(),
|
||||||
|
env->performance_entry_callback(),
|
||||||
|
1, &object);
|
||||||
}
|
}
|
||||||
Local<Context> context = env->context();
|
|
||||||
Isolate* isolate = env->isolate();
|
|
||||||
Local<Value> argv = entry->object();
|
|
||||||
env->performance_entry_callback()->Call(context,
|
|
||||||
v8::Undefined(isolate),
|
|
||||||
1, &argv).ToLocalChecked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a User Timing Mark
|
||||||
void Mark(const FunctionCallbackInfo<Value>& args) {
|
void Mark(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
Local<Context> context = env->context();
|
HandleScope scope(env->isolate());
|
||||||
Isolate* isolate = env->isolate();
|
Utf8Value name(env->isolate(), args[0]);
|
||||||
Utf8Value name(isolate, args[0]);
|
|
||||||
uint64_t now = PERFORMANCE_NOW();
|
uint64_t now = PERFORMANCE_NOW();
|
||||||
auto marks = env->performance_marks();
|
auto marks = env->performance_marks();
|
||||||
(*marks)[*name] = now;
|
(*marks)[*name] = now;
|
||||||
@ -68,25 +108,27 @@ void Mark(const FunctionCallbackInfo<Value>& args) {
|
|||||||
// TODO(jasnell): Once Tracing API is fully implemented, this should
|
// TODO(jasnell): Once Tracing API is fully implemented, this should
|
||||||
// record a trace event also.
|
// record a trace event also.
|
||||||
|
|
||||||
Local<Function> fn = env->performance_entry_template();
|
PerformanceEntry entry(env, *name, "mark", now, now);
|
||||||
Local<Object> obj = fn->NewInstance(context).ToLocalChecked();
|
Local<Object> obj = entry.ToObject();
|
||||||
new PerformanceEntry(env, obj, *name, "mark", now, now);
|
PerformanceEntry::Notify(env, entry.kind(), obj);
|
||||||
args.GetReturnValue().Set(obj);
|
args.GetReturnValue().Set(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline uint64_t GetPerformanceMark(Environment* env, std::string name) {
|
inline uint64_t GetPerformanceMark(Environment* env, std::string name) {
|
||||||
auto marks = env->performance_marks();
|
auto marks = env->performance_marks();
|
||||||
auto res = marks->find(name);
|
auto res = marks->find(name);
|
||||||
return res != marks->end() ? res->second : 0;
|
return res != marks->end() ? res->second : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a User Timing Measure. A Measure is a PerformanceEntry that
|
||||||
|
// measures the duration between two distinct user timing marks
|
||||||
void Measure(const FunctionCallbackInfo<Value>& args) {
|
void Measure(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
Local<Context> context = env->context();
|
HandleScope scope(env->isolate());
|
||||||
Isolate* isolate = env->isolate();
|
Utf8Value name(env->isolate(), args[0]);
|
||||||
Utf8Value name(isolate, args[0]);
|
Utf8Value startMark(env->isolate(), args[1]);
|
||||||
Utf8Value startMark(isolate, args[1]);
|
Utf8Value endMark(env->isolate(), args[2]);
|
||||||
Utf8Value endMark(isolate, args[2]);
|
|
||||||
|
|
||||||
double* milestones = env->performance_state()->milestones;
|
double* milestones = env->performance_state()->milestones;
|
||||||
|
|
||||||
@ -113,41 +155,13 @@ void Measure(const FunctionCallbackInfo<Value>& args) {
|
|||||||
// TODO(jasnell): Once Tracing API is fully implemented, this should
|
// TODO(jasnell): Once Tracing API is fully implemented, this should
|
||||||
// record a trace event also.
|
// record a trace event also.
|
||||||
|
|
||||||
Local<Function> fn = env->performance_entry_template();
|
PerformanceEntry entry(env, *name, "measure", startTimestamp, endTimestamp);
|
||||||
Local<Object> obj = fn->NewInstance(context).ToLocalChecked();
|
Local<Object> obj = entry.ToObject();
|
||||||
new PerformanceEntry(env, obj, *name, "measure",
|
PerformanceEntry::Notify(env, entry.kind(), obj);
|
||||||
startTimestamp, endTimestamp);
|
|
||||||
args.GetReturnValue().Set(obj);
|
args.GetReturnValue().Set(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetPerformanceEntryName(const FunctionCallbackInfo<Value>& info) {
|
// Allows specific Node.js lifecycle milestones to be set from JavaScript
|
||||||
Isolate* isolate = info.GetIsolate();
|
|
||||||
PerformanceEntry* entry;
|
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&entry, info.Holder());
|
|
||||||
info.GetReturnValue().Set(
|
|
||||||
String::NewFromUtf8(isolate, entry->name().c_str(), String::kNormalString));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetPerformanceEntryType(const FunctionCallbackInfo<Value>& info) {
|
|
||||||
Isolate* isolate = info.GetIsolate();
|
|
||||||
PerformanceEntry* entry;
|
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&entry, info.Holder());
|
|
||||||
info.GetReturnValue().Set(
|
|
||||||
String::NewFromUtf8(isolate, entry->type().c_str(), String::kNormalString));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetPerformanceEntryStartTime(const FunctionCallbackInfo<Value>& info) {
|
|
||||||
PerformanceEntry* entry;
|
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&entry, info.Holder());
|
|
||||||
info.GetReturnValue().Set(entry->startTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetPerformanceEntryDuration(const FunctionCallbackInfo<Value>& info) {
|
|
||||||
PerformanceEntry* entry;
|
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&entry, info.Holder());
|
|
||||||
info.GetReturnValue().Set(entry->duration());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarkMilestone(const FunctionCallbackInfo<Value>& args) {
|
void MarkMilestone(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
@ -160,44 +174,35 @@ void MarkMilestone(const FunctionCallbackInfo<Value>& args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetupPerformanceObservers(const FunctionCallbackInfo<Value>& args) {
|
void SetupPerformanceObservers(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
CHECK(args[0]->IsFunction());
|
CHECK(args[0]->IsFunction());
|
||||||
env->set_performance_entry_callback(args[0].As<Function>());
|
env->set_performance_entry_callback(args[0].As<Function>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceGCCallback(uv_async_t* handle) {
|
// Creates a GC Performance Entry and passes it to observers
|
||||||
PerformanceEntry::Data* data =
|
void PerformanceGCCallback(Environment* env, void* ptr) {
|
||||||
static_cast<PerformanceEntry::Data*>(handle->data);
|
GCPerformanceEntry* entry = static_cast<GCPerformanceEntry*>(ptr);
|
||||||
Environment* env = data->env();
|
HandleScope scope(env->isolate());
|
||||||
Isolate* isolate = env->isolate();
|
|
||||||
HandleScope scope(isolate);
|
|
||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
Context::Scope context_scope(context);
|
|
||||||
Local<Function> fn;
|
|
||||||
Local<Object> obj;
|
|
||||||
PerformanceGCKind kind = static_cast<PerformanceGCKind>(data->data());
|
|
||||||
|
|
||||||
uint32_t* observers = env->performance_state()->observers;
|
uint32_t* observers = env->performance_state()->observers;
|
||||||
if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_GC]) {
|
if (observers[NODE_PERFORMANCE_ENTRY_TYPE_GC]) {
|
||||||
goto cleanup;
|
Local<Object> obj = entry->ToObject();
|
||||||
|
v8::PropertyAttribute attr =
|
||||||
|
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
|
||||||
|
obj->DefineOwnProperty(context,
|
||||||
|
FIXED_ONE_BYTE_STRING(env->isolate(), "kind"),
|
||||||
|
Integer::New(env->isolate(), entry->gckind()),
|
||||||
|
attr).FromJust();
|
||||||
|
PerformanceEntry::Notify(env, entry->kind(), obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn = env->performance_entry_template();
|
delete entry;
|
||||||
obj = fn->NewInstance(context).ToLocalChecked();
|
|
||||||
obj->Set(context,
|
|
||||||
FIXED_ONE_BYTE_STRING(isolate, "kind"),
|
|
||||||
Integer::New(isolate, kind)).FromJust();
|
|
||||||
new PerformanceEntry(env, obj, data);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
delete data;
|
|
||||||
auto closeCB = [](uv_handle_t* handle) {
|
|
||||||
delete reinterpret_cast<uv_async_t*>(handle);
|
|
||||||
};
|
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(handle), closeCB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marks the start of a GC cycle
|
||||||
void MarkGarbageCollectionStart(Isolate* isolate,
|
void MarkGarbageCollectionStart(Isolate* isolate,
|
||||||
v8::GCType type,
|
v8::GCType type,
|
||||||
v8::GCCallbackFlags flags) {
|
v8::GCCallbackFlags flags) {
|
||||||
@ -205,28 +210,27 @@ void MarkGarbageCollectionStart(Isolate* isolate,
|
|||||||
performance_last_gc_type_ = type;
|
performance_last_gc_type_ = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Marks the end of a GC cycle
|
||||||
void MarkGarbageCollectionEnd(Isolate* isolate,
|
void MarkGarbageCollectionEnd(Isolate* isolate,
|
||||||
v8::GCType type,
|
v8::GCType type,
|
||||||
v8::GCCallbackFlags flags,
|
v8::GCCallbackFlags flags,
|
||||||
void* data) {
|
void* data) {
|
||||||
Environment* env = static_cast<Environment*>(data);
|
Environment* env = static_cast<Environment*>(data);
|
||||||
uv_async_t* async = new uv_async_t(); // coverity[leaked_storage]
|
env->SetImmediate(PerformanceGCCallback,
|
||||||
if (uv_async_init(env->event_loop(), async, PerformanceGCCallback))
|
new GCPerformanceEntry(env,
|
||||||
return delete async;
|
static_cast<PerformanceGCKind>(type),
|
||||||
uv_unref(reinterpret_cast<uv_handle_t*>(async));
|
performance_last_gc_start_mark_,
|
||||||
async->data =
|
PERFORMANCE_NOW()));
|
||||||
new PerformanceEntry::Data(env, "gc", "gc",
|
|
||||||
performance_last_gc_start_mark_,
|
|
||||||
PERFORMANCE_NOW(), type);
|
|
||||||
CHECK_EQ(0, uv_async_send(async));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void SetupGarbageCollectionTracking(Environment* env) {
|
inline void SetupGarbageCollectionTracking(Environment* env) {
|
||||||
env->isolate()->AddGCPrologueCallback(MarkGarbageCollectionStart);
|
env->isolate()->AddGCPrologueCallback(MarkGarbageCollectionStart);
|
||||||
env->isolate()->AddGCEpilogueCallback(MarkGarbageCollectionEnd,
|
env->isolate()->AddGCEpilogueCallback(MarkGarbageCollectionEnd,
|
||||||
static_cast<void*>(env));
|
static_cast<void*>(env));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the name of a function
|
||||||
inline Local<Value> GetName(Local<Function> fn) {
|
inline Local<Value> GetName(Local<Function> fn) {
|
||||||
Local<Value> val = fn->GetDebugName();
|
Local<Value> val = fn->GetDebugName();
|
||||||
if (val.IsEmpty() || val->IsUndefined()) {
|
if (val.IsEmpty() || val->IsUndefined()) {
|
||||||
@ -238,6 +242,9 @@ inline Local<Value> GetName(Local<Function> fn) {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Executes a wrapped Function and captures timing information, causing a
|
||||||
|
// Function PerformanceEntry to be emitted to PerformanceObservers after
|
||||||
|
// execution.
|
||||||
void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
|
void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
|
||||||
Isolate* isolate = args.GetIsolate();
|
Isolate* isolate = args.GetIsolate();
|
||||||
HandleScope scope(isolate);
|
HandleScope scope(isolate);
|
||||||
@ -247,9 +254,8 @@ void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
|
|||||||
size_t count = args.Length();
|
size_t count = args.Length();
|
||||||
size_t idx;
|
size_t idx;
|
||||||
std::vector<Local<Value>> call_args;
|
std::vector<Local<Value>> call_args;
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i)
|
||||||
call_args.push_back(args[i]);
|
call_args.push_back(args[i]);
|
||||||
}
|
|
||||||
|
|
||||||
Utf8Value name(isolate, GetName(fn));
|
Utf8Value name(isolate, GetName(fn));
|
||||||
|
|
||||||
@ -286,15 +292,14 @@ void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
|
|||||||
if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION])
|
if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Local<Function> ctor = env->performance_entry_template();
|
PerformanceEntry entry(env, *name, "function", start, end);
|
||||||
v8::MaybeLocal<Object> instance = ctor->NewInstance(context);
|
Local<Object> obj = entry.ToObject();
|
||||||
Local<Object> obj = instance.ToLocalChecked();
|
for (idx = 0; idx < count; idx++)
|
||||||
for (idx = 0; idx < count; idx++) {
|
obj->Set(context, idx, args[idx]).FromJust();
|
||||||
obj->Set(context, idx, args[idx]).ToChecked();
|
PerformanceEntry::Notify(env, entry.kind(), obj);
|
||||||
}
|
|
||||||
new PerformanceEntry(env, obj, *name, "function", start, end);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wraps a Function in a TimerFunctionCall
|
||||||
void Timerify(const FunctionCallbackInfo<Value>& args) {
|
void Timerify(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
@ -307,6 +312,7 @@ void Timerify(const FunctionCallbackInfo<Value>& args) {
|
|||||||
args.GetReturnValue().Set(wrap);
|
args.GetReturnValue().Set(wrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Init(Local<Object> target,
|
void Init(Local<Object> target,
|
||||||
Local<Value> unused,
|
Local<Value> unused,
|
||||||
Local<Context> context) {
|
Local<Context> context) {
|
||||||
@ -329,55 +335,10 @@ void Init(Local<Object> target,
|
|||||||
Local<String> performanceEntryString =
|
Local<String> performanceEntryString =
|
||||||
FIXED_ONE_BYTE_STRING(isolate, "PerformanceEntry");
|
FIXED_ONE_BYTE_STRING(isolate, "PerformanceEntry");
|
||||||
|
|
||||||
Local<FunctionTemplate> pe = env->NewFunctionTemplate(PerformanceEntry::New);
|
Local<FunctionTemplate> pe = FunctionTemplate::New(isolate);
|
||||||
pe->InstanceTemplate()->SetInternalFieldCount(1);
|
|
||||||
pe->SetClassName(performanceEntryString);
|
pe->SetClassName(performanceEntryString);
|
||||||
|
|
||||||
Local<Signature> signature = Signature::New(env->isolate(), pe);
|
|
||||||
|
|
||||||
Local<FunctionTemplate> get_performance_entry_name_templ =
|
|
||||||
FunctionTemplate::New(env->isolate(),
|
|
||||||
GetPerformanceEntryName,
|
|
||||||
env->as_external(),
|
|
||||||
signature);
|
|
||||||
|
|
||||||
Local<FunctionTemplate> get_performance_entry_type_templ =
|
|
||||||
FunctionTemplate::New(env->isolate(),
|
|
||||||
GetPerformanceEntryType,
|
|
||||||
env->as_external(),
|
|
||||||
signature);
|
|
||||||
|
|
||||||
Local<FunctionTemplate> get_performance_entry_start_time_templ =
|
|
||||||
FunctionTemplate::New(env->isolate(),
|
|
||||||
GetPerformanceEntryStartTime,
|
|
||||||
env->as_external(),
|
|
||||||
signature);
|
|
||||||
|
|
||||||
Local<FunctionTemplate> get_performance_entry_duration_templ =
|
|
||||||
FunctionTemplate::New(env->isolate(),
|
|
||||||
GetPerformanceEntryDuration,
|
|
||||||
env->as_external(),
|
|
||||||
signature);
|
|
||||||
|
|
||||||
Local<ObjectTemplate> ot = pe->InstanceTemplate();
|
|
||||||
ot->SetAccessorProperty(env->name_string(),
|
|
||||||
get_performance_entry_name_templ,
|
|
||||||
Local<FunctionTemplate>());
|
|
||||||
|
|
||||||
ot->SetAccessorProperty(FIXED_ONE_BYTE_STRING(isolate, "entryType"),
|
|
||||||
get_performance_entry_type_templ,
|
|
||||||
Local<FunctionTemplate>());
|
|
||||||
|
|
||||||
ot->SetAccessorProperty(FIXED_ONE_BYTE_STRING(isolate, "startTime"),
|
|
||||||
get_performance_entry_start_time_templ,
|
|
||||||
Local<FunctionTemplate>());
|
|
||||||
|
|
||||||
ot->SetAccessorProperty(FIXED_ONE_BYTE_STRING(isolate, "duration"),
|
|
||||||
get_performance_entry_duration_templ,
|
|
||||||
Local<FunctionTemplate>());
|
|
||||||
|
|
||||||
Local<Function> fn = pe->GetFunction();
|
Local<Function> fn = pe->GetFunction();
|
||||||
target->Set(performanceEntryString, fn);
|
target->Set(context, performanceEntryString, fn).FromJust();
|
||||||
env->set_performance_entry_template(fn);
|
env->set_performance_entry_template(fn);
|
||||||
|
|
||||||
env->SetMethod(target, "mark", Mark);
|
env->SetMethod(target, "mark", Mark);
|
||||||
|
142
src/node_perf.h
142
src/node_perf.h
@ -42,120 +42,51 @@ static inline PerformanceEntryType ToPerformanceEntryTypeEnum(
|
|||||||
NODE_EXTERN inline void MarkPerformanceMilestone(
|
NODE_EXTERN inline void MarkPerformanceMilestone(
|
||||||
Environment* env,
|
Environment* env,
|
||||||
PerformanceMilestone milestone) {
|
PerformanceMilestone milestone) {
|
||||||
env->performance_state()->milestones[milestone] = PERFORMANCE_NOW();
|
env->performance_state()->milestones[milestone] = PERFORMANCE_NOW();
|
||||||
}
|
}
|
||||||
|
|
||||||
class PerformanceEntry : public BaseObject {
|
class PerformanceEntry {
|
||||||
public:
|
public:
|
||||||
// Used for temporary storage of performance entry details when the
|
static inline void Notify(Environment* env,
|
||||||
// object cannot be created immediately.
|
PerformanceEntryType type,
|
||||||
class Data {
|
Local<Value> object);
|
||||||
public:
|
|
||||||
Data(
|
|
||||||
Environment* env,
|
|
||||||
const char* name,
|
|
||||||
const char* type,
|
|
||||||
uint64_t startTime,
|
|
||||||
uint64_t endTime,
|
|
||||||
int data = 0) :
|
|
||||||
env_(env),
|
|
||||||
name_(name),
|
|
||||||
type_(type),
|
|
||||||
startTime_(startTime),
|
|
||||||
endTime_(endTime),
|
|
||||||
data_(data) {}
|
|
||||||
|
|
||||||
Environment* env() const {
|
|
||||||
return env_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& name() const {
|
|
||||||
return name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& type() const {
|
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t startTime() const {
|
|
||||||
return startTime_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t endTime() const {
|
|
||||||
return endTime_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int data() const {
|
|
||||||
return data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Environment* const env_;
|
|
||||||
const std::string name_;
|
|
||||||
const std::string type_;
|
|
||||||
const uint64_t startTime_;
|
|
||||||
const uint64_t endTime_;
|
|
||||||
const int data_;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void NotifyObservers(Environment* env, PerformanceEntry* entry);
|
|
||||||
|
|
||||||
static void New(const FunctionCallbackInfo<Value>& args);
|
static void New(const FunctionCallbackInfo<Value>& args);
|
||||||
|
|
||||||
PerformanceEntry(Environment* env,
|
PerformanceEntry(Environment* env,
|
||||||
Local<Object> wrap,
|
|
||||||
const char* name,
|
const char* name,
|
||||||
const char* type,
|
const char* type,
|
||||||
uint64_t startTime,
|
uint64_t startTime,
|
||||||
uint64_t endTime) :
|
uint64_t endTime) : env_(env),
|
||||||
BaseObject(env, wrap),
|
name_(name),
|
||||||
name_(name),
|
type_(type),
|
||||||
type_(type),
|
startTime_(startTime),
|
||||||
startTime_(startTime),
|
endTime_(endTime) { }
|
||||||
endTime_(endTime) {
|
|
||||||
MakeWeak<PerformanceEntry>(this);
|
virtual ~PerformanceEntry() { }
|
||||||
NotifyObservers(env, this);
|
|
||||||
|
virtual const Local<Object> ToObject() const;
|
||||||
|
|
||||||
|
Environment* env() const { return env_; }
|
||||||
|
|
||||||
|
const std::string& name() const { return name_; }
|
||||||
|
|
||||||
|
const std::string& type() const { return type_; }
|
||||||
|
|
||||||
|
PerformanceEntryType kind() {
|
||||||
|
return ToPerformanceEntryTypeEnum(type().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceEntry(Environment* env,
|
double startTime() const { return startTime_ / 1e6; }
|
||||||
Local<Object> wrap,
|
|
||||||
Data* data) :
|
|
||||||
BaseObject(env, wrap),
|
|
||||||
name_(data->name()),
|
|
||||||
type_(data->type()),
|
|
||||||
startTime_(data->startTime()),
|
|
||||||
endTime_(data->endTime()) {
|
|
||||||
MakeWeak<PerformanceEntry>(this);
|
|
||||||
NotifyObservers(env, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
~PerformanceEntry() {}
|
double duration() const { return durationNano() / 1e6; }
|
||||||
|
|
||||||
const std::string& name() const {
|
uint64_t startTimeNano() const { return startTime_; }
|
||||||
return name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& type() const {
|
uint64_t durationNano() const { return endTime_ - startTime_; }
|
||||||
return type_;
|
|
||||||
}
|
|
||||||
|
|
||||||
double startTime() const {
|
|
||||||
return startTime_ / 1e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
double duration() const {
|
|
||||||
return durationNano() / 1e6;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t startTimeNano() const {
|
|
||||||
return startTime_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t durationNano() const {
|
|
||||||
return endTime_ - startTime_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Environment* env_;
|
||||||
const std::string name_;
|
const std::string name_;
|
||||||
const std::string type_;
|
const std::string type_;
|
||||||
const uint64_t startTime_;
|
const uint64_t startTime_;
|
||||||
@ -169,6 +100,21 @@ enum PerformanceGCKind {
|
|||||||
NODE_PERFORMANCE_GC_WEAKCB = GCType::kGCTypeProcessWeakCallbacks
|
NODE_PERFORMANCE_GC_WEAKCB = GCType::kGCTypeProcessWeakCallbacks
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GCPerformanceEntry : public PerformanceEntry {
|
||||||
|
public:
|
||||||
|
GCPerformanceEntry(Environment* env,
|
||||||
|
PerformanceGCKind gckind,
|
||||||
|
uint64_t startTime,
|
||||||
|
uint64_t endTime) :
|
||||||
|
PerformanceEntry(env, "gc", "gc", startTime, endTime),
|
||||||
|
gckind_(gckind) { }
|
||||||
|
|
||||||
|
PerformanceGCKind gckind() const { return gckind_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
PerformanceGCKind gckind_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace performance
|
} // namespace performance
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user