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::Local;
|
||||
using v8::Name;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::ObjectTemplate;
|
||||
using v8::Signature;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
@ -30,37 +29,78 @@ uint64_t performance_v8_start;
|
||||
uint64_t performance_last_gc_start_mark_ = 0;
|
||||
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) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Isolate* isolate = env->isolate();
|
||||
Utf8Value name(isolate, args[0]);
|
||||
Utf8Value type(isolate, args[1]);
|
||||
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,
|
||||
PerformanceEntry* entry) {
|
||||
// Pass the PerformanceEntry object to the PerformanceObservers
|
||||
inline void PerformanceEntry::Notify(Environment* env,
|
||||
PerformanceEntryType type,
|
||||
Local<Value> object) {
|
||||
Context::Scope scope(env->context());
|
||||
uint32_t* observers = env->performance_state()->observers;
|
||||
PerformanceEntryType type = ToPerformanceEntryTypeEnum(entry->type().c_str());
|
||||
if (observers == nullptr ||
|
||||
type == NODE_PERFORMANCE_ENTRY_TYPE_INVALID ||
|
||||
!observers[type]) {
|
||||
return;
|
||||
if (observers != nullptr &&
|
||||
type != NODE_PERFORMANCE_ENTRY_TYPE_INVALID &&
|
||||
observers[type]) {
|
||||
node::MakeCallback(env->isolate(),
|
||||
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) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Local<Context> context = env->context();
|
||||
Isolate* isolate = env->isolate();
|
||||
Utf8Value name(isolate, args[0]);
|
||||
HandleScope scope(env->isolate());
|
||||
Utf8Value name(env->isolate(), args[0]);
|
||||
uint64_t now = PERFORMANCE_NOW();
|
||||
auto marks = env->performance_marks();
|
||||
(*marks)[*name] = now;
|
||||
@ -68,25 +108,27 @@ void Mark(const FunctionCallbackInfo<Value>& args) {
|
||||
// TODO(jasnell): Once Tracing API is fully implemented, this should
|
||||
// record a trace event also.
|
||||
|
||||
Local<Function> fn = env->performance_entry_template();
|
||||
Local<Object> obj = fn->NewInstance(context).ToLocalChecked();
|
||||
new PerformanceEntry(env, obj, *name, "mark", now, now);
|
||||
PerformanceEntry entry(env, *name, "mark", now, now);
|
||||
Local<Object> obj = entry.ToObject();
|
||||
PerformanceEntry::Notify(env, entry.kind(), obj);
|
||||
args.GetReturnValue().Set(obj);
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t GetPerformanceMark(Environment* env, std::string name) {
|
||||
auto marks = env->performance_marks();
|
||||
auto res = marks->find(name);
|
||||
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) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Local<Context> context = env->context();
|
||||
Isolate* isolate = env->isolate();
|
||||
Utf8Value name(isolate, args[0]);
|
||||
Utf8Value startMark(isolate, args[1]);
|
||||
Utf8Value endMark(isolate, args[2]);
|
||||
HandleScope scope(env->isolate());
|
||||
Utf8Value name(env->isolate(), args[0]);
|
||||
Utf8Value startMark(env->isolate(), args[1]);
|
||||
Utf8Value endMark(env->isolate(), args[2]);
|
||||
|
||||
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
|
||||
// record a trace event also.
|
||||
|
||||
Local<Function> fn = env->performance_entry_template();
|
||||
Local<Object> obj = fn->NewInstance(context).ToLocalChecked();
|
||||
new PerformanceEntry(env, obj, *name, "measure",
|
||||
startTimestamp, endTimestamp);
|
||||
PerformanceEntry entry(env, *name, "measure", startTimestamp, endTimestamp);
|
||||
Local<Object> obj = entry.ToObject();
|
||||
PerformanceEntry::Notify(env, entry.kind(), obj);
|
||||
args.GetReturnValue().Set(obj);
|
||||
}
|
||||
|
||||
void GetPerformanceEntryName(const FunctionCallbackInfo<Value>& info) {
|
||||
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());
|
||||
}
|
||||
|
||||
// Allows specific Node.js lifecycle milestones to be set from JavaScript
|
||||
void MarkMilestone(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Local<Context> context = env->context();
|
||||
@ -160,44 +174,35 @@ void MarkMilestone(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupPerformanceObservers(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
CHECK(args[0]->IsFunction());
|
||||
env->set_performance_entry_callback(args[0].As<Function>());
|
||||
}
|
||||
|
||||
void PerformanceGCCallback(uv_async_t* handle) {
|
||||
PerformanceEntry::Data* data =
|
||||
static_cast<PerformanceEntry::Data*>(handle->data);
|
||||
Environment* env = data->env();
|
||||
Isolate* isolate = env->isolate();
|
||||
HandleScope scope(isolate);
|
||||
// Creates a GC Performance Entry and passes it to observers
|
||||
void PerformanceGCCallback(Environment* env, void* ptr) {
|
||||
GCPerformanceEntry* entry = static_cast<GCPerformanceEntry*>(ptr);
|
||||
HandleScope scope(env->isolate());
|
||||
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;
|
||||
if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_GC]) {
|
||||
goto cleanup;
|
||||
if (observers[NODE_PERFORMANCE_ENTRY_TYPE_GC]) {
|
||||
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();
|
||||
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);
|
||||
delete entry;
|
||||
}
|
||||
|
||||
// Marks the start of a GC cycle
|
||||
void MarkGarbageCollectionStart(Isolate* isolate,
|
||||
v8::GCType type,
|
||||
v8::GCCallbackFlags flags) {
|
||||
@ -205,28 +210,27 @@ void MarkGarbageCollectionStart(Isolate* isolate,
|
||||
performance_last_gc_type_ = type;
|
||||
}
|
||||
|
||||
// Marks the end of a GC cycle
|
||||
void MarkGarbageCollectionEnd(Isolate* isolate,
|
||||
v8::GCType type,
|
||||
v8::GCCallbackFlags flags,
|
||||
void* data) {
|
||||
Environment* env = static_cast<Environment*>(data);
|
||||
uv_async_t* async = new uv_async_t(); // coverity[leaked_storage]
|
||||
if (uv_async_init(env->event_loop(), async, PerformanceGCCallback))
|
||||
return delete async;
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(async));
|
||||
async->data =
|
||||
new PerformanceEntry::Data(env, "gc", "gc",
|
||||
performance_last_gc_start_mark_,
|
||||
PERFORMANCE_NOW(), type);
|
||||
CHECK_EQ(0, uv_async_send(async));
|
||||
env->SetImmediate(PerformanceGCCallback,
|
||||
new GCPerformanceEntry(env,
|
||||
static_cast<PerformanceGCKind>(type),
|
||||
performance_last_gc_start_mark_,
|
||||
PERFORMANCE_NOW()));
|
||||
}
|
||||
|
||||
|
||||
inline void SetupGarbageCollectionTracking(Environment* env) {
|
||||
env->isolate()->AddGCPrologueCallback(MarkGarbageCollectionStart);
|
||||
env->isolate()->AddGCEpilogueCallback(MarkGarbageCollectionEnd,
|
||||
static_cast<void*>(env));
|
||||
}
|
||||
|
||||
// Gets the name of a function
|
||||
inline Local<Value> GetName(Local<Function> fn) {
|
||||
Local<Value> val = fn->GetDebugName();
|
||||
if (val.IsEmpty() || val->IsUndefined()) {
|
||||
@ -238,6 +242,9 @@ inline Local<Value> GetName(Local<Function> fn) {
|
||||
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) {
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
HandleScope scope(isolate);
|
||||
@ -247,9 +254,8 @@ void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
|
||||
size_t count = args.Length();
|
||||
size_t idx;
|
||||
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]);
|
||||
}
|
||||
|
||||
Utf8Value name(isolate, GetName(fn));
|
||||
|
||||
@ -286,15 +292,14 @@ void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
|
||||
if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION])
|
||||
return;
|
||||
|
||||
Local<Function> ctor = env->performance_entry_template();
|
||||
v8::MaybeLocal<Object> instance = ctor->NewInstance(context);
|
||||
Local<Object> obj = instance.ToLocalChecked();
|
||||
for (idx = 0; idx < count; idx++) {
|
||||
obj->Set(context, idx, args[idx]).ToChecked();
|
||||
}
|
||||
new PerformanceEntry(env, obj, *name, "function", start, end);
|
||||
PerformanceEntry entry(env, *name, "function", start, end);
|
||||
Local<Object> obj = entry.ToObject();
|
||||
for (idx = 0; idx < count; idx++)
|
||||
obj->Set(context, idx, args[idx]).FromJust();
|
||||
PerformanceEntry::Notify(env, entry.kind(), obj);
|
||||
}
|
||||
|
||||
// Wraps a Function in a TimerFunctionCall
|
||||
void Timerify(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
Local<Context> context = env->context();
|
||||
@ -307,6 +312,7 @@ void Timerify(const FunctionCallbackInfo<Value>& args) {
|
||||
args.GetReturnValue().Set(wrap);
|
||||
}
|
||||
|
||||
|
||||
void Init(Local<Object> target,
|
||||
Local<Value> unused,
|
||||
Local<Context> context) {
|
||||
@ -329,55 +335,10 @@ void Init(Local<Object> target,
|
||||
Local<String> performanceEntryString =
|
||||
FIXED_ONE_BYTE_STRING(isolate, "PerformanceEntry");
|
||||
|
||||
Local<FunctionTemplate> pe = env->NewFunctionTemplate(PerformanceEntry::New);
|
||||
pe->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
Local<FunctionTemplate> pe = FunctionTemplate::New(isolate);
|
||||
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();
|
||||
target->Set(performanceEntryString, fn);
|
||||
target->Set(context, performanceEntryString, fn).FromJust();
|
||||
env->set_performance_entry_template(fn);
|
||||
|
||||
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(
|
||||
Environment* env,
|
||||
PerformanceMilestone milestone) {
|
||||
env->performance_state()->milestones[milestone] = PERFORMANCE_NOW();
|
||||
}
|
||||
env->performance_state()->milestones[milestone] = PERFORMANCE_NOW();
|
||||
}
|
||||
|
||||
class PerformanceEntry : public BaseObject {
|
||||
class PerformanceEntry {
|
||||
public:
|
||||
// Used for temporary storage of performance entry details when the
|
||||
// object cannot be created immediately.
|
||||
class Data {
|
||||
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 inline void Notify(Environment* env,
|
||||
PerformanceEntryType type,
|
||||
Local<Value> object);
|
||||
|
||||
static void New(const FunctionCallbackInfo<Value>& args);
|
||||
|
||||
PerformanceEntry(Environment* env,
|
||||
Local<Object> wrap,
|
||||
const char* name,
|
||||
const char* type,
|
||||
uint64_t startTime,
|
||||
uint64_t endTime) :
|
||||
BaseObject(env, wrap),
|
||||
name_(name),
|
||||
type_(type),
|
||||
startTime_(startTime),
|
||||
endTime_(endTime) {
|
||||
MakeWeak<PerformanceEntry>(this);
|
||||
NotifyObservers(env, this);
|
||||
uint64_t endTime) : env_(env),
|
||||
name_(name),
|
||||
type_(type),
|
||||
startTime_(startTime),
|
||||
endTime_(endTime) { }
|
||||
|
||||
virtual ~PerformanceEntry() { }
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
double startTime() const { return startTime_ / 1e6; }
|
||||
|
||||
~PerformanceEntry() {}
|
||||
double duration() const { return durationNano() / 1e6; }
|
||||
|
||||
const std::string& name() const {
|
||||
return name_;
|
||||
}
|
||||
uint64_t startTimeNano() const { return startTime_; }
|
||||
|
||||
const std::string& type() const {
|
||||
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_;
|
||||
}
|
||||
uint64_t durationNano() const { return endTime_ - startTime_; }
|
||||
|
||||
private:
|
||||
Environment* env_;
|
||||
const std::string name_;
|
||||
const std::string type_;
|
||||
const uint64_t startTime_;
|
||||
@ -169,6 +100,21 @@ enum PerformanceGCKind {
|
||||
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 node
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user