#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 namespace node { class Environment; class ExternalReferenceRegistry; namespace performance { 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 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 GetDetails( Environment* env, const PerformanceEntry& 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 detail; if (!Traits::GetDetails(env, *this).ToLocal(&detail)) { // TODO(@jasnell): Handle the error here return; } v8::Local 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 GetDetails( Environment* env, const PerformanceEntry& entry); }; using GCPerformanceEntry = PerformanceEntry; } // namespace performance } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_PERF_H_