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