• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef SRC_NODE_PERF_H_
2 #define SRC_NODE_PERF_H_
3 
4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5 
6 #include "base_object-inl.h"
7 #include "histogram.h"
8 #include "node.h"
9 #include "node_internals.h"
10 #include "node_perf_common.h"
11 
12 #include "v8.h"
13 #include "uv.h"
14 
15 #include <string>
16 
17 namespace node {
18 
19 class Environment;
20 class ExternalReferenceRegistry;
21 
22 namespace performance {
23 
24 extern const uint64_t timeOrigin;
25 
GetPerformanceMilestoneName(PerformanceMilestone milestone)26 inline const char* GetPerformanceMilestoneName(
27     PerformanceMilestone milestone) {
28   switch (milestone) {
29 #define V(name, label) case NODE_PERFORMANCE_MILESTONE_##name: return label;
30   NODE_PERFORMANCE_MILESTONES(V)
31 #undef V
32     default:
33       UNREACHABLE();
34   }
35 }
36 
ToPerformanceMilestoneEnum(const char * str)37 inline PerformanceMilestone ToPerformanceMilestoneEnum(const char* str) {
38 #define V(name, label)                                                        \
39   if (strcmp(str, label) == 0) return NODE_PERFORMANCE_MILESTONE_##name;
40   NODE_PERFORMANCE_MILESTONES(V)
41 #undef V
42   return NODE_PERFORMANCE_MILESTONE_INVALID;
43 }
44 
GetPerformanceEntryTypeName(PerformanceEntryType type)45 inline const char* GetPerformanceEntryTypeName(
46     PerformanceEntryType type) {
47   switch (type) {
48 #define V(name, label) case NODE_PERFORMANCE_ENTRY_TYPE_##name: return label;
49   NODE_PERFORMANCE_ENTRY_TYPES(V)
50 #undef V
51     default:
52       UNREACHABLE();
53   }
54 }
55 
ToPerformanceEntryTypeEnum(const char * type)56 inline PerformanceEntryType ToPerformanceEntryTypeEnum(
57     const char* type) {
58 #define V(name, label)                                                        \
59   if (strcmp(type, label) == 0) return NODE_PERFORMANCE_ENTRY_TYPE_##name;
60   NODE_PERFORMANCE_ENTRY_TYPES(V)
61 #undef V
62   return NODE_PERFORMANCE_ENTRY_TYPE_INVALID;
63 }
64 
65 enum PerformanceGCKind {
66   NODE_PERFORMANCE_GC_MAJOR = v8::GCType::kGCTypeMarkSweepCompact,
67   NODE_PERFORMANCE_GC_MINOR = v8::GCType::kGCTypeScavenge,
68   NODE_PERFORMANCE_GC_INCREMENTAL = v8::GCType::kGCTypeIncrementalMarking,
69   NODE_PERFORMANCE_GC_WEAKCB = v8::GCType::kGCTypeProcessWeakCallbacks
70 };
71 
72 enum PerformanceGCFlags {
73   NODE_PERFORMANCE_GC_FLAGS_NO =
74     v8::GCCallbackFlags::kNoGCCallbackFlags,
75   NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED =
76     v8::GCCallbackFlags::kGCCallbackFlagConstructRetainedObjectInfos,
77   NODE_PERFORMANCE_GC_FLAGS_FORCED =
78     v8::GCCallbackFlags::kGCCallbackFlagForced,
79   NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING =
80     v8::GCCallbackFlags::kGCCallbackFlagSynchronousPhantomCallbackProcessing,
81   NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE =
82     v8::GCCallbackFlags::kGCCallbackFlagCollectAllAvailableGarbage,
83   NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY =
84     v8::GCCallbackFlags::kGCCallbackFlagCollectAllExternalMemory,
85   NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE =
86     v8::GCCallbackFlags::kGCCallbackScheduleIdleGarbageCollection
87 };
88 
89 template <typename Traits>
90 struct PerformanceEntry {
91   using Details = typename Traits::Details;
92   std::string name;
93   double start_time;
94   double duration;
95   Details details;
96 
PerformanceEntryPerformanceEntry97   PerformanceEntry(
98     const std::string& name_,
99     double start_time_,
100     double duration_,
101     const Details& details_)
102     : name(name_),
103       start_time(start_time_),
104       duration(duration_),
105       details(details_) {}
106 
GetDetailsPerformanceEntry107   static v8::MaybeLocal<v8::Object> GetDetails(
108       Environment* env,
109       const PerformanceEntry<Traits>& entry) {
110     return Traits::GetDetails(env, entry);
111   }
112 
NotifyPerformanceEntry113   void Notify(Environment* env) {
114     v8::HandleScope handle_scope(env->isolate());
115     v8::Context::Scope scope(env->context());
116     AliasedUint32Array& observers = env->performance_state()->observers;
117     if (env->performance_entry_callback().IsEmpty() ||
118         !observers[Traits::kType]) {
119       return;
120     }
121 
122     v8::Local<v8::Object> detail;
123     if (!Traits::GetDetails(env, *this).ToLocal(&detail)) {
124       // TODO(@jasnell): Handle the error here
125       return;
126     }
127 
128     v8::Local<v8::Value> argv[] = {
129       OneByteString(env->isolate(), name.c_str()),
130       OneByteString(env->isolate(), GetPerformanceEntryTypeName(Traits::kType)),
131       v8::Number::New(env->isolate(), start_time),
132       v8::Number::New(env->isolate(), duration),
133       detail
134     };
135 
136     node::MakeSyncCallback(
137         env->isolate(),
138         env->context()->Global(),
139         env->performance_entry_callback(),
140         arraysize(argv),
141         argv);
142   }
143 };
144 
145 struct GCPerformanceEntryTraits {
146   static constexpr PerformanceEntryType kType =
147       NODE_PERFORMANCE_ENTRY_TYPE_GC;
148   struct Details {
149     PerformanceGCKind kind;
150     PerformanceGCFlags flags;
151 
DetailsGCPerformanceEntryTraits::Details152     Details(PerformanceGCKind kind_, PerformanceGCFlags flags_)
153         : kind(kind_), flags(flags_) {}
154   };
155 
156   static v8::MaybeLocal<v8::Object> GetDetails(
157       Environment* env,
158       const PerformanceEntry<GCPerformanceEntryTraits>& entry);
159 };
160 
161 using GCPerformanceEntry = PerformanceEntry<GCPerformanceEntryTraits>;
162 
163 }  // namespace performance
164 }  // namespace node
165 
166 #endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
167 
168 #endif  // SRC_NODE_PERF_H_
169