GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_perf.cc Lines: 299 331 90.3 %
Date: 2019-05-05 22:32:45 Branches: 117 184 63.6 %

Line Branch Exec Source
1
#include "aliased_buffer.h"
2
#include "node_internals.h"
3
#include "node_perf.h"
4
#include "node_buffer.h"
5
#include "node_process.h"
6
7
#include <cinttypes>
8
9
namespace node {
10
namespace performance {
11
12
using v8::Array;
13
using v8::Context;
14
using v8::DontDelete;
15
using v8::Function;
16
using v8::FunctionCallbackInfo;
17
using v8::FunctionTemplate;
18
using v8::GCCallbackFlags;
19
using v8::GCType;
20
using v8::HandleScope;
21
using v8::Integer;
22
using v8::Isolate;
23
using v8::Local;
24
using v8::Map;
25
using v8::MaybeLocal;
26
using v8::Name;
27
using v8::NewStringType;
28
using v8::Number;
29
using v8::Object;
30
using v8::PropertyAttribute;
31
using v8::ReadOnly;
32
using v8::String;
33
using v8::Uint32Array;
34
using v8::Value;
35
36
// Microseconds in a millisecond, as a float.
37
#define MICROS_PER_MILLIS 1e3
38
39
// https://w3c.github.io/hr-time/#dfn-time-origin
40
4525
const uint64_t timeOrigin = PERFORMANCE_NOW();
41
// https://w3c.github.io/hr-time/#dfn-time-origin-timestamp
42
4525
const double timeOriginTimestamp = GetCurrentTimeInMicroseconds();
43
uint64_t performance_v8_start;
44
45
27259
void performance_state::Mark(enum PerformanceMilestone milestone,
46
                             uint64_t ts) {
47
27259
  this->milestones[milestone] = ts;
48

54518
  TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(
49
      TRACING_CATEGORY_NODE1(bootstrap),
50
      GetPerformanceMilestoneName(milestone),
51
      TRACE_EVENT_SCOPE_THREAD, ts / 1000);
52
27259
}
53
54
// Initialize the performance entry object properties
55
36
inline void InitObject(const PerformanceEntry& entry, Local<Object> obj) {
56
36
  Environment* env = entry.env();
57
36
  Isolate* isolate = env->isolate();
58
36
  Local<Context> context = env->context();
59
  PropertyAttribute attr =
60
36
      static_cast<PropertyAttribute>(ReadOnly | DontDelete);
61
  obj->DefineOwnProperty(context,
62
                         env->name_string(),
63
                         String::NewFromUtf8(isolate,
64
36
                                             entry.name().c_str(),
65
36
                                             NewStringType::kNormal)
66
                             .ToLocalChecked(),
67
144
                         attr)
68
72
      .Check();
69
  obj->DefineOwnProperty(context,
70
                         env->entry_type_string(),
71
                         String::NewFromUtf8(isolate,
72
36
                                             entry.type().c_str(),
73
36
                                             NewStringType::kNormal)
74
                             .ToLocalChecked(),
75
144
                         attr)
76
72
      .Check();
77
  obj->DefineOwnProperty(context,
78
                         env->start_time_string(),
79
                         Number::New(isolate, entry.startTime()),
80
144
                         attr).Check();
81
  obj->DefineOwnProperty(context,
82
                         env->duration_string(),
83
                         Number::New(isolate, entry.duration()),
84
144
                         attr).Check();
85
36
}
86
87
// Create a new PerformanceEntry object
88
36
MaybeLocal<Object> PerformanceEntry::ToObject() const {
89
  Local<Object> obj;
90
108
  if (!env_->performance_entry_template()
91
144
           ->NewInstance(env_->context())
92
108
           .ToLocal(&obj)) {
93
    return MaybeLocal<Object>();
94
  }
95
36
  InitObject(*this, obj);
96
36
  return obj;
97
}
98
99
// Allow creating a PerformanceEntry object from JavaScript
100
void PerformanceEntry::New(const FunctionCallbackInfo<Value>& args) {
101
  Environment* env = Environment::GetCurrent(args);
102
  Isolate* isolate = env->isolate();
103
  Utf8Value name(isolate, args[0]);
104
  Utf8Value type(isolate, args[1]);
105
  uint64_t now = PERFORMANCE_NOW();
106
  PerformanceEntry entry(env, *name, *type, now, now);
107
  Local<Object> obj = args.This();
108
  InitObject(entry, obj);
109
  PerformanceEntry::Notify(env, entry.kind(), obj);
110
}
111
112
// Pass the PerformanceEntry object to the PerformanceObservers
113
36
void PerformanceEntry::Notify(Environment* env,
114
                              PerformanceEntryType type,
115
                              Local<Value> object) {
116
36
  Context::Scope scope(env->context());
117
36
  AliasedUint32Array& observers = env->performance_state()->observers;
118

144
  if (type != NODE_PERFORMANCE_ENTRY_TYPE_INVALID &&
119
144
      observers[type]) {
120
    node::MakeCallback(env->isolate(),
121
                       object.As<Object>(),
122
                       env->performance_entry_callback(),
123
                       1, &object,
124
26
                       node::async_context{0, 0});
125
  }
126
36
}
127
128
// Create a User Timing Mark
129
19
void Mark(const FunctionCallbackInfo<Value>& args) {
130
19
  Environment* env = Environment::GetCurrent(args);
131
19
  HandleScope scope(env->isolate());
132
38
  Utf8Value name(env->isolate(), args[0]);
133
19
  uint64_t now = PERFORMANCE_NOW();
134
19
  auto marks = env->performance_marks();
135
19
  (*marks)[*name] = now;
136
137

38
  TRACE_EVENT_COPY_MARK_WITH_TIMESTAMP(
138
      TRACING_CATEGORY_NODE2(perf, usertiming),
139
      *name, now / 1000);
140
141
38
  PerformanceEntry entry(env, *name, "mark", now, now);
142
  Local<Object> obj;
143
57
  if (!entry.ToObject().ToLocal(&obj)) return;
144
19
  PerformanceEntry::Notify(env, entry.kind(), obj);
145
57
  args.GetReturnValue().Set(obj);
146
}
147
148
3
void ClearMark(const FunctionCallbackInfo<Value>& args) {
149
3
  Environment* env = Environment::GetCurrent(args);
150
3
  auto marks = env->performance_marks();
151
152
3
  if (args.Length() == 0) {
153
2
    marks->clear();
154
  } else {
155
1
    Utf8Value name(env->isolate(), args[0]);
156
1
    marks->erase(*name);
157
  }
158
3
}
159
160
20
inline uint64_t GetPerformanceMark(Environment* env, const std::string& name) {
161
20
  auto marks = env->performance_marks();
162
20
  auto res = marks->find(name);
163
20
  return res != marks->end() ? res->second : 0;
164
}
165
166
// Create a User Timing Measure. A Measure is a PerformanceEntry that
167
// measures the duration between two distinct user timing marks
168
10
void Measure(const FunctionCallbackInfo<Value>& args) {
169
10
  Environment* env = Environment::GetCurrent(args);
170
10
  HandleScope scope(env->isolate());
171
20
  Utf8Value name(env->isolate(), args[0]);
172
20
  Utf8Value startMark(env->isolate(), args[1]);
173
20
  Utf8Value endMark(env->isolate(), args[2]);
174
175
10
  AliasedFloat64Array& milestones = env->performance_state()->milestones;
176
177
10
  uint64_t startTimestamp = timeOrigin;
178
10
  uint64_t start = GetPerformanceMark(env, *startMark);
179
10
  if (start != 0) {
180
5
    startTimestamp = start;
181
  } else {
182
5
    PerformanceMilestone milestone = ToPerformanceMilestoneEnum(*startMark);
183
5
    if (milestone != NODE_PERFORMANCE_MILESTONE_INVALID)
184
      startTimestamp = milestones[milestone];
185
  }
186
187
10
  uint64_t endTimestamp = GetPerformanceMark(env, *endMark);
188
10
  if (endTimestamp == 0) {
189
    PerformanceMilestone milestone = ToPerformanceMilestoneEnum(*endMark);
190
    if (milestone != NODE_PERFORMANCE_MILESTONE_INVALID)
191
      endTimestamp = milestones[milestone];
192
  }
193
194
10
  if (endTimestamp < startTimestamp)
195
    endTimestamp = startTimestamp;
196
197

20
  TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
198
      TRACING_CATEGORY_NODE2(perf, usertiming),
199
      *name, *name, startTimestamp / 1000);
200

20
  TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
201
      TRACING_CATEGORY_NODE2(perf, usertiming),
202
      *name, *name, endTimestamp / 1000);
203
204
20
  PerformanceEntry entry(env, *name, "measure", startTimestamp, endTimestamp);
205
  Local<Object> obj;
206
30
  if (!entry.ToObject().ToLocal(&obj)) return;
207
10
  PerformanceEntry::Notify(env, entry.kind(), obj);
208
30
  args.GetReturnValue().Set(obj);
209
}
210
211
// Allows specific Node.js lifecycle milestones to be set from JavaScript
212
void MarkMilestone(const FunctionCallbackInfo<Value>& args) {
213
  Environment* env = Environment::GetCurrent(args);
214
  Local<Context> context = env->context();
215
  PerformanceMilestone milestone =
216
      static_cast<PerformanceMilestone>(
217
          args[0]->Int32Value(context).ToChecked());
218
  if (milestone != NODE_PERFORMANCE_MILESTONE_INVALID)
219
    env->performance_state()->Mark(milestone);
220
}
221
222
223
14
void SetupPerformanceObservers(const FunctionCallbackInfo<Value>& args) {
224
14
  Environment* env = Environment::GetCurrent(args);
225
28
  CHECK(args[0]->IsFunction());
226
28
  env->set_performance_entry_callback(args[0].As<Function>());
227
14
}
228
229
// Creates a GC Performance Entry and passes it to observers
230
1
void PerformanceGCCallback(Environment* env, void* ptr) {
231
  std::unique_ptr<GCPerformanceEntry> entry{
232
1
      static_cast<GCPerformanceEntry*>(ptr)};
233
2
  HandleScope scope(env->isolate());
234
1
  Local<Context> context = env->context();
235
236
1
  AliasedUint32Array& observers = env->performance_state()->observers;
237
1
  if (observers[NODE_PERFORMANCE_ENTRY_TYPE_GC]) {
238
    Local<Object> obj;
239
3
    if (!entry->ToObject().ToLocal(&obj)) return;
240
    PropertyAttribute attr =
241
1
        static_cast<PropertyAttribute>(ReadOnly | DontDelete);
242
    obj->DefineOwnProperty(context,
243
                           env->kind_string(),
244
1
                           Integer::New(env->isolate(), entry->gckind()),
245
4
                           attr).Check();
246
1
    PerformanceEntry::Notify(env, entry->kind(), obj);
247
1
  }
248
}
249
250
// Marks the start of a GC cycle
251
2
void MarkGarbageCollectionStart(Isolate* isolate,
252
                                GCType type,
253
                                GCCallbackFlags flags,
254
                                void* data) {
255
2
  Environment* env = static_cast<Environment*>(data);
256
2
  env->performance_state()->performance_last_gc_start_mark = PERFORMANCE_NOW();
257
2
}
258
259
// Marks the end of a GC cycle
260
2
void MarkGarbageCollectionEnd(Isolate* isolate,
261
                              GCType type,
262
                              GCCallbackFlags flags,
263
                              void* data) {
264
2
  Environment* env = static_cast<Environment*>(data);
265
2
  performance_state* state = env->performance_state();
266
  // If no one is listening to gc performance entries, do not create them.
267
2
  if (!state->observers[NODE_PERFORMANCE_ENTRY_TYPE_GC])
268
3
    return;
269
  GCPerformanceEntry* entry =
270
      new GCPerformanceEntry(env,
271
                             static_cast<PerformanceGCKind>(type),
272
                             state->performance_last_gc_start_mark,
273
1
                             PERFORMANCE_NOW());
274
  env->SetUnrefImmediate(PerformanceGCCallback,
275
1
                         entry);
276
}
277
278
1
static void SetupGarbageCollectionTracking(
279
    const FunctionCallbackInfo<Value>& args) {
280
1
  Environment* env = Environment::GetCurrent(args);
281
282
  env->isolate()->AddGCPrologueCallback(MarkGarbageCollectionStart,
283
1
                                        static_cast<void*>(env));
284
  env->isolate()->AddGCEpilogueCallback(MarkGarbageCollectionEnd,
285
1
                                        static_cast<void*>(env));
286
3
  env->AddCleanupHook([](void* data) {
287
1
    Environment* env = static_cast<Environment*>(data);
288
1
    env->isolate()->RemoveGCPrologueCallback(MarkGarbageCollectionStart, data);
289
1
    env->isolate()->RemoveGCEpilogueCallback(MarkGarbageCollectionEnd, data);
290
4
  }, env);
291
1
}
292
293
// Gets the name of a function
294
7
inline Local<Value> GetName(Local<Function> fn) {
295
7
  Local<Value> val = fn->GetDebugName();
296

21
  if (val.IsEmpty() || val->IsUndefined()) {
297
    Local<Value> boundFunction = fn->GetBoundFunction();
298
    if (!boundFunction.IsEmpty() && !boundFunction->IsUndefined()) {
299
      val = GetName(boundFunction.As<Function>());
300
    }
301
  }
302
7
  return val;
303
}
304
305
// Executes a wrapped Function and captures timing information, causing a
306
// Function PerformanceEntry to be emitted to PerformanceObservers after
307
// execution.
308
7
void TimerFunctionCall(const FunctionCallbackInfo<Value>& args) {
309
7
  Isolate* isolate = args.GetIsolate();
310
7
  Local<Context> context = isolate->GetCurrentContext();
311
7
  Environment* env = Environment::GetCurrent(context);
312
7
  CHECK_NOT_NULL(env);
313
14
  Local<Function> fn = args.Data().As<Function>();
314
7
  size_t count = args.Length();
315
  size_t idx;
316
7
  SlicedArguments call_args(args);
317
9
  Utf8Value name(isolate, GetName(fn));
318
7
  bool is_construct_call = args.IsConstructCall();
319
320
7
  uint64_t start = PERFORMANCE_NOW();
321

14
  TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
322
      TRACING_CATEGORY_NODE2(perf, timerify),
323
      *name, *name, start / 1000);
324
  v8::MaybeLocal<Value> ret;
325
326
7
  if (is_construct_call) {
327
2
    ret = fn->NewInstance(context, call_args.length(), call_args.out())
328
2
        .FromMaybe(Local<Object>());
329
  } else {
330
12
    ret = fn->Call(context, args.This(), call_args.length(), call_args.out());
331
  }
332
333
7
  uint64_t end = PERFORMANCE_NOW();
334

14
  TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
335
      TRACING_CATEGORY_NODE2(perf, timerify),
336
      *name, *name, end / 1000);
337
338
7
  if (ret.IsEmpty())
339
1
    return;
340
12
  args.GetReturnValue().Set(ret.ToLocalChecked());
341
342
6
  AliasedUint32Array& observers = env->performance_state()->observers;
343
6
  if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION])
344
4
    return;
345
346
4
  PerformanceEntry entry(env, *name, "function", start, end);
347
  Local<Object> obj;
348
4
  if (!entry.ToObject().ToLocal(&obj)) return;
349
4
  for (idx = 0; idx < count; idx++)
350
8
    obj->Set(context, idx, args[idx]).Check();
351
4
  PerformanceEntry::Notify(env, entry.kind(), obj);
352
}
353
354
// Wraps a Function in a TimerFunctionCall
355
8
void Timerify(const FunctionCallbackInfo<Value>& args) {
356
8
  Environment* env = Environment::GetCurrent(args);
357
8
  Local<Context> context = env->context();
358
16
  CHECK(args[0]->IsFunction());
359
16
  CHECK(args[1]->IsNumber());
360
16
  Local<Function> fn = args[0].As<Function>();
361
24
  int length = args[1]->IntegerValue(context).ToChecked();
362
  Local<Function> wrap =
363
16
      Function::New(context, TimerFunctionCall, fn, length).ToLocalChecked();
364
16
  args.GetReturnValue().Set(wrap);
365
8
}
366
367
// Event Loop Timing Histogram
368
namespace {
369
2
static void ELDHistogramMin(const FunctionCallbackInfo<Value>& args) {
370
  ELDHistogram* histogram;
371
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
372
2
  double value = static_cast<double>(histogram->Min());
373
4
  args.GetReturnValue().Set(value);
374
}
375
376
2
static void ELDHistogramMax(const FunctionCallbackInfo<Value>& args) {
377
  ELDHistogram* histogram;
378
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
379
2
  double value = static_cast<double>(histogram->Max());
380
4
  args.GetReturnValue().Set(value);
381
}
382
383
2
static void ELDHistogramMean(const FunctionCallbackInfo<Value>& args) {
384
  ELDHistogram* histogram;
385
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
386
6
  args.GetReturnValue().Set(histogram->Mean());
387
}
388
389
static void ELDHistogramExceeds(const FunctionCallbackInfo<Value>& args) {
390
  ELDHistogram* histogram;
391
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
392
  double value = static_cast<double>(histogram->Exceeds());
393
  args.GetReturnValue().Set(value);
394
}
395
396
2
static void ELDHistogramStddev(const FunctionCallbackInfo<Value>& args) {
397
  ELDHistogram* histogram;
398
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
399
6
  args.GetReturnValue().Set(histogram->Stddev());
400
}
401
402
991
static void ELDHistogramPercentile(const FunctionCallbackInfo<Value>& args) {
403
  ELDHistogram* histogram;
404
1982
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
405
1982
  CHECK(args[0]->IsNumber());
406
2973
  double percentile = args[0].As<Number>()->Value();
407
2973
  args.GetReturnValue().Set(histogram->Percentile(percentile));
408
}
409
410
2
static void ELDHistogramPercentiles(const FunctionCallbackInfo<Value>& args) {
411
2
  Environment* env = Environment::GetCurrent(args);
412
  ELDHistogram* histogram;
413
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
414
4
  CHECK(args[0]->IsMap());
415
4
  Local<Map> map = args[0].As<Map>();
416
14
  histogram->Percentiles([&](double key, double value) {
417
    map->Set(env->context(),
418
             Number::New(env->isolate(), key),
419
70
             Number::New(env->isolate(), value)).IsEmpty();
420
16
  });
421
}
422
423
3
static void ELDHistogramEnable(const FunctionCallbackInfo<Value>& args) {
424
  ELDHistogram* histogram;
425
6
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
426
9
  args.GetReturnValue().Set(histogram->Enable());
427
}
428
429
3
static void ELDHistogramDisable(const FunctionCallbackInfo<Value>& args) {
430
  ELDHistogram* histogram;
431
6
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
432
9
  args.GetReturnValue().Set(histogram->Disable());
433
}
434
435
2
static void ELDHistogramReset(const FunctionCallbackInfo<Value>& args) {
436
  ELDHistogram* histogram;
437
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
438
2
  histogram->ResetState();
439
}
440
441
2
static void ELDHistogramNew(const FunctionCallbackInfo<Value>& args) {
442
2
  Environment* env = Environment::GetCurrent(args);
443
2
  CHECK(args.IsConstructCall());
444
8
  int32_t resolution = args[0]->IntegerValue(env->context()).FromJust();
445
2
  CHECK_GT(resolution, 0);
446
2
  new ELDHistogram(env, args.This(), resolution);
447
2
}
448
}  // namespace
449
450
2
ELDHistogram::ELDHistogram(
451
    Environment* env,
452
    Local<Object> wrap,
453
    int32_t resolution) : BaseObject(env, wrap),
454
                          Histogram(1, 3.6e12),
455
2
                          resolution_(resolution) {
456
2
  MakeWeak();
457
2
  timer_ = new uv_timer_t();
458
2
  uv_timer_init(env->event_loop(), timer_);
459
2
  timer_->data = this;
460
2
}
461
462
2
void ELDHistogram::CloseTimer() {
463
2
  if (timer_ == nullptr)
464
2
    return;
465
466
4
  env()->CloseHandle(timer_, [](uv_timer_t* handle) { delete handle; });
467
2
  timer_ = nullptr;
468
}
469
470
6
ELDHistogram::~ELDHistogram() {
471
2
  Disable();
472
2
  CloseTimer();
473
4
}
474
475
1886
void ELDHistogramDelayInterval(uv_timer_t* req) {
476
  ELDHistogram* histogram =
477
1886
    reinterpret_cast<ELDHistogram*>(req->data);
478
1886
  histogram->RecordDelta();
479

3772
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
480
                 "min", histogram->Min());
481

3772
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
482
                 "max", histogram->Max());
483

3772
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
484
                 "mean", histogram->Mean());
485

3772
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
486
                 "stddev", histogram->Stddev());
487
1886
}
488
489
1886
bool ELDHistogram::RecordDelta() {
490
1886
  uint64_t time = uv_hrtime();
491
1886
  bool ret = true;
492
1886
  if (prev_ > 0) {
493
1885
    int64_t delta = time - prev_;
494
1885
    if (delta > 0) {
495
1885
      ret = Record(delta);
496

3770
      TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
497
                     "delay", delta);
498
1885
      if (!ret) {
499
        if (exceeds_ < 0xFFFFFFFF)
500
          exceeds_++;
501
        ProcessEmitWarning(
502
            env(),
503
            "Event loop delay exceeded 1 hour: %" PRId64 " nanoseconds",
504
            delta);
505
      }
506
    }
507
  }
508
1886
  prev_ = time;
509
1886
  return ret;
510
}
511
512
3
bool ELDHistogram::Enable() {
513
3
  if (enabled_) return false;
514
2
  enabled_ = true;
515
2
  prev_ = 0;
516
  uv_timer_start(timer_,
517
                 ELDHistogramDelayInterval,
518
                 resolution_,
519
2
                 resolution_);
520
2
  uv_unref(reinterpret_cast<uv_handle_t*>(timer_));
521
2
  return true;
522
}
523
524
5
bool ELDHistogram::Disable() {
525
5
  if (!enabled_) return false;
526
2
  enabled_ = false;
527
2
  uv_timer_stop(timer_);
528
2
  return true;
529
}
530
531
14
void Initialize(Local<Object> target,
532
                Local<Value> unused,
533
                Local<Context> context,
534
                void* priv) {
535
14
  Environment* env = Environment::GetCurrent(context);
536
14
  Isolate* isolate = env->isolate();
537
14
  performance_state* state = env->performance_state();
538
539
  target->Set(context,
540
              FIXED_ONE_BYTE_STRING(isolate, "observerCounts"),
541
56
              state->observers.GetJSArray()).Check();
542
  target->Set(context,
543
              FIXED_ONE_BYTE_STRING(isolate, "milestones"),
544
56
              state->milestones.GetJSArray()).Check();
545
546
  Local<String> performanceEntryString =
547
14
      FIXED_ONE_BYTE_STRING(isolate, "PerformanceEntry");
548
549
14
  Local<FunctionTemplate> pe = FunctionTemplate::New(isolate);
550
14
  pe->SetClassName(performanceEntryString);
551
28
  Local<Function> fn = pe->GetFunction(context).ToLocalChecked();
552
28
  target->Set(context, performanceEntryString, fn).Check();
553
14
  env->set_performance_entry_template(fn);
554
555
14
  env->SetMethod(target, "clearMark", ClearMark);
556
14
  env->SetMethod(target, "mark", Mark);
557
14
  env->SetMethod(target, "measure", Measure);
558
14
  env->SetMethod(target, "markMilestone", MarkMilestone);
559
14
  env->SetMethod(target, "setupObservers", SetupPerformanceObservers);
560
14
  env->SetMethod(target, "timerify", Timerify);
561
  env->SetMethod(
562
14
      target, "setupGarbageCollectionTracking", SetupGarbageCollectionTracking);
563
564
14
  Local<Object> constants = Object::New(isolate);
565
566
56
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_MAJOR);
567
56
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_MINOR);
568
56
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_INCREMENTAL);
569
56
  NODE_DEFINE_CONSTANT(constants, NODE_PERFORMANCE_GC_WEAKCB);
570
571
#define V(name, _)                                                            \
572
  NODE_DEFINE_HIDDEN_CONSTANT(constants, NODE_PERFORMANCE_ENTRY_TYPE_##name);
573
336
  NODE_PERFORMANCE_ENTRY_TYPES(V)
574
#undef V
575
576
#define V(name, _)                                                            \
577
  NODE_DEFINE_HIDDEN_CONSTANT(constants, NODE_PERFORMANCE_MILESTONE_##name);
578
336
  NODE_PERFORMANCE_MILESTONES(V)
579
#undef V
580
581
  PropertyAttribute attr =
582
14
      static_cast<PropertyAttribute>(ReadOnly | DontDelete);
583
584
  target->DefineOwnProperty(context,
585
                            FIXED_ONE_BYTE_STRING(isolate, "timeOrigin"),
586
                            Number::New(isolate, timeOrigin / 1e6),
587
56
                            attr).ToChecked();
588
589
  target->DefineOwnProperty(
590
      context,
591
      FIXED_ONE_BYTE_STRING(isolate, "timeOriginTimestamp"),
592
      Number::New(isolate, timeOriginTimestamp / MICROS_PER_MILLIS),
593
56
      attr).ToChecked();
594
595
  target->DefineOwnProperty(context,
596
                            env->constants_string(),
597
                            constants,
598
42
                            attr).ToChecked();
599
600
14
  Local<String> eldh_classname = FIXED_ONE_BYTE_STRING(isolate, "ELDHistogram");
601
  Local<FunctionTemplate> eldh =
602
14
      env->NewFunctionTemplate(ELDHistogramNew);
603
14
  eldh->SetClassName(eldh_classname);
604
28
  eldh->InstanceTemplate()->SetInternalFieldCount(1);
605
14
  env->SetProtoMethod(eldh, "exceeds", ELDHistogramExceeds);
606
14
  env->SetProtoMethod(eldh, "min", ELDHistogramMin);
607
14
  env->SetProtoMethod(eldh, "max", ELDHistogramMax);
608
14
  env->SetProtoMethod(eldh, "mean", ELDHistogramMean);
609
14
  env->SetProtoMethod(eldh, "stddev", ELDHistogramStddev);
610
14
  env->SetProtoMethod(eldh, "percentile", ELDHistogramPercentile);
611
14
  env->SetProtoMethod(eldh, "percentiles", ELDHistogramPercentiles);
612
14
  env->SetProtoMethod(eldh, "enable", ELDHistogramEnable);
613
14
  env->SetProtoMethod(eldh, "disable", ELDHistogramDisable);
614
14
  env->SetProtoMethod(eldh, "reset", ELDHistogramReset);
615
  target->Set(context, eldh_classname,
616
56
              eldh->GetFunction(env->context()).ToLocalChecked()).Check();
617
14
}
618
619
}  // namespace performance
620
}  // namespace node
621
622

18099
NODE_MODULE_CONTEXT_AWARE_INTERNAL(performance, node::performance::Initialize)