| #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 { |
| |
| 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_ |