GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: node_perf.h Lines: 21 30 70.0 %
Date: 2022-08-17 04:19:55 Branches: 12 31 38.7 %

Line Branch Exec Source
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
46
inline const char* GetPerformanceMilestoneName(
25
    PerformanceMilestone milestone) {
26

46
  switch (milestone) {
27
#define V(name, label) case NODE_PERFORMANCE_MILESTONE_##name: return label;
28
46
  NODE_PERFORMANCE_MILESTONES(V)
29
#undef V
30
    default:
31
      UNREACHABLE();
32
  }
33
}
34
35
inline PerformanceMilestone ToPerformanceMilestoneEnum(const char* str) {
36
#define V(name, label)                                                        \
37
  if (strcmp(str, label) == 0) return NODE_PERFORMANCE_MILESTONE_##name;
38
  NODE_PERFORMANCE_MILESTONES(V)
39
#undef V
40
  return NODE_PERFORMANCE_MILESTONE_INVALID;
41
}
42
43
16
inline const char* GetPerformanceEntryTypeName(
44
    PerformanceEntryType type) {
45

16
  switch (type) {
46
#define V(name, label) case NODE_PERFORMANCE_ENTRY_TYPE_##name: return label;
47
16
  NODE_PERFORMANCE_ENTRY_TYPES(V)
48
#undef V
49
    default:
50
      UNREACHABLE();
51
  }
52
}
53
54
inline PerformanceEntryType ToPerformanceEntryTypeEnum(
55
    const char* type) {
56
#define V(name, label)                                                        \
57
  if (strcmp(type, label) == 0) return NODE_PERFORMANCE_ENTRY_TYPE_##name;
58
  NODE_PERFORMANCE_ENTRY_TYPES(V)
59
#undef V
60
  return NODE_PERFORMANCE_ENTRY_TYPE_INVALID;
61
}
62
63
enum PerformanceGCKind {
64
  NODE_PERFORMANCE_GC_MAJOR = v8::GCType::kGCTypeMarkSweepCompact,
65
  NODE_PERFORMANCE_GC_MINOR = v8::GCType::kGCTypeScavenge,
66
  NODE_PERFORMANCE_GC_INCREMENTAL = v8::GCType::kGCTypeIncrementalMarking,
67
  NODE_PERFORMANCE_GC_WEAKCB = v8::GCType::kGCTypeProcessWeakCallbacks
68
};
69
70
enum PerformanceGCFlags {
71
  NODE_PERFORMANCE_GC_FLAGS_NO =
72
    v8::GCCallbackFlags::kNoGCCallbackFlags,
73
  NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED =
74
    v8::GCCallbackFlags::kGCCallbackFlagConstructRetainedObjectInfos,
75
  NODE_PERFORMANCE_GC_FLAGS_FORCED =
76
    v8::GCCallbackFlags::kGCCallbackFlagForced,
77
  NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING =
78
    v8::GCCallbackFlags::kGCCallbackFlagSynchronousPhantomCallbackProcessing,
79
  NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE =
80
    v8::GCCallbackFlags::kGCCallbackFlagCollectAllAvailableGarbage,
81
  NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY =
82
    v8::GCCallbackFlags::kGCCallbackFlagCollectAllExternalMemory,
83
  NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE =
84
    v8::GCCallbackFlags::kGCCallbackScheduleIdleGarbageCollection
85
};
86
87
template <typename Traits>
88
struct PerformanceEntry {
89
  using Details = typename Traits::Details;
90
  std::string name;
91
  double start_time;
92
  double duration;
93
  Details details;
94
95
31
  PerformanceEntry(
96
    const std::string& name_,
97
    double start_time_,
98
    double duration_,
99
    const Details& details_)
100
    : name(name_),
101
      start_time(start_time_),
102
      duration(duration_),
103
31
      details(details_) {}
104
105
  static v8::MaybeLocal<v8::Object> GetDetails(
106
      Environment* env,
107
      const PerformanceEntry<Traits>& entry) {
108
    return Traits::GetDetails(env, entry);
109
  }
110
111
16
  void Notify(Environment* env) {
112
16
    v8::HandleScope handle_scope(env->isolate());
113
16
    v8::Context::Scope scope(env->context());
114
16
    AliasedUint32Array& observers = env->performance_state()->observers;
115

48
    if (env->performance_entry_callback().IsEmpty() ||
116
32
        !observers[Traits::kType]) {
117
      return;
118
    }
119
120
    v8::Local<v8::Object> detail;
121
32
    if (!Traits::GetDetails(env, *this).ToLocal(&detail)) {
122
      // TODO(@jasnell): Handle the error here
123
      return;
124
    }
125
126
80
    v8::Local<v8::Value> argv[] = {
127
      OneByteString(env->isolate(), name.c_str()),
128
      OneByteString(env->isolate(), GetPerformanceEntryTypeName(Traits::kType)),
129
      v8::Number::New(env->isolate(), start_time),
130
      v8::Number::New(env->isolate(), duration),
131
      detail
132
    };
133
134
32
    node::MakeSyncCallback(
135
        env->isolate(),
136
32
        env->context()->Global(),
137
        env->performance_entry_callback(),
138
16
        arraysize(argv),
139
        argv);
140
  }
141
};
142
143
struct GCPerformanceEntryTraits {
144
  static constexpr PerformanceEntryType kType =
145
      NODE_PERFORMANCE_ENTRY_TYPE_GC;
146
  struct Details {
147
    PerformanceGCKind kind;
148
    PerformanceGCFlags flags;
149
150
1
    Details(PerformanceGCKind kind_, PerformanceGCFlags flags_)
151
1
        : kind(kind_), flags(flags_) {}
152
  };
153
154
  static v8::MaybeLocal<v8::Object> GetDetails(
155
      Environment* env,
156
      const PerformanceEntry<GCPerformanceEntryTraits>& entry);
157
};
158
159
using GCPerformanceEntry = PerformanceEntry<GCPerformanceEntryTraits>;
160
161
}  // namespace performance
162
}  // namespace node
163
164
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
165
166
#endif  // SRC_NODE_PERF_H_