#ifndef SRC_NODE_PERF_H_
#define SRC_NODE_PERF_H_
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "base_object-inl.h"
#include "histogram.h"
#include "node.h"
#include "node_internals.h"
#include "node_perf_common.h"
#include "v8.h"
#include "uv.h"
#include <string>
namespace node {
class Environment;
class ExternalReferenceRegistry;
namespace performance {
extern const uint64_t timeOrigin;
inline const char* GetPerformanceMilestoneName(
PerformanceMilestone milestone) {
switch (milestone) {
#define V(name, label) case NODE_PERFORMANCE_MILESTONE_##name: return label;
NODE_PERFORMANCE_MILESTONES(V)
#undef V
default:
UNREACHABLE();
}
}
inline PerformanceMilestone ToPerformanceMilestoneEnum(const char* str) {
#define V(name, label) \
if (strcmp(str, label) == 0) return NODE_PERFORMANCE_MILESTONE_##name;
NODE_PERFORMANCE_MILESTONES(V)
#undef V
return NODE_PERFORMANCE_MILESTONE_INVALID;
}
inline const char* GetPerformanceEntryTypeName(
PerformanceEntryType type) {
switch (type) {
#define V(name, label) case NODE_PERFORMANCE_ENTRY_TYPE_##name: return label;
NODE_PERFORMANCE_ENTRY_TYPES(V)
#undef V
default:
UNREACHABLE();
}
}
inline PerformanceEntryType ToPerformanceEntryTypeEnum(
const char* type) {
#define V(name, label) \
if (strcmp(type, label) == 0) return NODE_PERFORMANCE_ENTRY_TYPE_##name;
NODE_PERFORMANCE_ENTRY_TYPES(V)
#undef V
return NODE_PERFORMANCE_ENTRY_TYPE_INVALID;
}
enum PerformanceGCKind {
NODE_PERFORMANCE_GC_MAJOR = v8::GCType::kGCTypeMarkSweepCompact,
NODE_PERFORMANCE_GC_MINOR = v8::GCType::kGCTypeScavenge,
NODE_PERFORMANCE_GC_INCREMENTAL = v8::GCType::kGCTypeIncrementalMarking,
NODE_PERFORMANCE_GC_WEAKCB = v8::GCType::kGCTypeProcessWeakCallbacks
};
enum PerformanceGCFlags {
NODE_PERFORMANCE_GC_FLAGS_NO =
v8::GCCallbackFlags::kNoGCCallbackFlags,
NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED =
v8::GCCallbackFlags::kGCCallbackFlagConstructRetainedObjectInfos,
NODE_PERFORMANCE_GC_FLAGS_FORCED =
v8::GCCallbackFlags::kGCCallbackFlagForced,
NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING =
v8::GCCallbackFlags::kGCCallbackFlagSynchronousPhantomCallbackProcessing,
NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE =
v8::GCCallbackFlags::kGCCallbackFlagCollectAllAvailableGarbage,
NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY =
v8::GCCallbackFlags::kGCCallbackFlagCollectAllExternalMemory,
NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE =
v8::GCCallbackFlags::kGCCallbackScheduleIdleGarbageCollection
};
template <typename Traits>
struct PerformanceEntry {
using Details = typename Traits::Details;
std::string name;
double start_time;
double duration;
Details details;
PerformanceEntry(
const std::string& name_,
double start_time_,
double duration_,
const Details& details_)
: name(name_),
start_time(start_time_),
duration(duration_),
details(details_) {}
static v8::MaybeLocal<v8::Object> GetDetails(
Environment* env,
const PerformanceEntry<Traits>& entry) {
return Traits::GetDetails(env, entry);
}
void Notify(Environment* env) {
v8::HandleScope handle_scope(env->isolate());
v8::Context::Scope scope(env->context());
AliasedUint32Array& observers = env->performance_state()->observers;
if (env->performance_entry_callback().IsEmpty() ||
!observers[Traits::kType]) {
return;
}
v8::Local<v8::Object> detail;
if (!Traits::GetDetails(env, *this).ToLocal(&detail)) {
// TODO(@jasnell): Handle the error here
return;
}
v8::Local<v8::Value> argv[] = {
OneByteString(env->isolate(), name.c_str()),
OneByteString(env->isolate(), GetPerformanceEntryTypeName(Traits::kType)),
v8::Number::New(env->isolate(), start_time),
v8::Number::New(env->isolate(), duration),
detail
};
node::MakeSyncCallback(
env->isolate(),
env->context()->Global(),
env->performance_entry_callback(),
arraysize(argv),
argv);
}
};
struct GCPerformanceEntryTraits {
static constexpr PerformanceEntryType kType =
NODE_PERFORMANCE_ENTRY_TYPE_GC;
struct Details {
PerformanceGCKind kind;
PerformanceGCFlags flags;
Details(PerformanceGCKind kind_, PerformanceGCFlags flags_)
: kind(kind_), flags(flags_) {}
};
static v8::MaybeLocal<v8::Object> GetDetails(
Environment* env,
const PerformanceEntry<GCPerformanceEntryTraits>& entry);
};
using GCPerformanceEntry = PerformanceEntry<GCPerformanceEntryTraits>;
} // namespace performance
} // namespace node
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#endif // SRC_NODE_PERF_H_
|