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: 311 343 90.7 %
Date: 2019-07-27 22:37:30 Branches: 121 192 63.0 %

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

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

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

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

20
  TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(
200
      TRACING_CATEGORY_NODE2(perf, usertiming),
201
      *name, *name, startTimestamp / 1000);
202

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

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

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

14
  TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(
337
      TRACING_CATEGORY_NODE2(perf, timerify),
338
      *name, *name, end / 1000);
339
340
7
  if (ret.IsEmpty())
341
1
    return;
342
12
  args.GetReturnValue().Set(ret.ToLocalChecked());
343
344
6
  AliasedUint32Array& observers = env->performance_state()->observers;
345
6
  if (!observers[NODE_PERFORMANCE_ENTRY_TYPE_FUNCTION])
346
4
    return;
347
348
4
  PerformanceEntry entry(env, *name, "function", start, end);
349
  Local<Object> obj;
350
4
  if (!entry.ToObject().ToLocal(&obj)) return;
351
4
  for (idx = 0; idx < count; idx++)
352
8
    obj->Set(context, idx, args[idx]).Check();
353
4
  PerformanceEntry::Notify(env, entry.kind(), obj);
354
}
355
356
// Wraps a Function in a TimerFunctionCall
357
8
void Timerify(const FunctionCallbackInfo<Value>& args) {
358
8
  Environment* env = Environment::GetCurrent(args);
359
8
  Local<Context> context = env->context();
360
16
  CHECK(args[0]->IsFunction());
361
16
  CHECK(args[1]->IsNumber());
362
16
  Local<Function> fn = args[0].As<Function>();
363
24
  int length = args[1]->IntegerValue(context).ToChecked();
364
  Local<Function> wrap =
365
16
      Function::New(context, TimerFunctionCall, fn, length).ToLocalChecked();
366
16
  args.GetReturnValue().Set(wrap);
367
8
}
368
369
// Notify a custom PerformanceEntry to observers
370
2
void Notify(const FunctionCallbackInfo<Value>& args) {
371
2
  Environment* env = Environment::GetCurrent(args);
372
2
  Utf8Value type(env->isolate(), args[0]);
373
2
  Local<Value> entry = args[1];
374
2
  PerformanceEntryType entry_type = ToPerformanceEntryTypeEnum(*type);
375
2
  AliasedUint32Array& observers = env->performance_state()->observers;
376

8
  if (entry_type != NODE_PERFORMANCE_ENTRY_TYPE_INVALID &&
377
8
      observers[entry_type]) {
378
    USE(env->performance_entry_callback()->
379
6
      Call(env->context(), Undefined(env->isolate()), 1, &entry));
380
2
  }
381
2
}
382
383
384
// Event Loop Timing Histogram
385
namespace {
386
2
static void ELDHistogramMin(const FunctionCallbackInfo<Value>& args) {
387
  ELDHistogram* histogram;
388
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
389
2
  double value = static_cast<double>(histogram->Min());
390
4
  args.GetReturnValue().Set(value);
391
}
392
393
2
static void ELDHistogramMax(const FunctionCallbackInfo<Value>& args) {
394
  ELDHistogram* histogram;
395
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
396
2
  double value = static_cast<double>(histogram->Max());
397
4
  args.GetReturnValue().Set(value);
398
}
399
400
2
static void ELDHistogramMean(const FunctionCallbackInfo<Value>& args) {
401
  ELDHistogram* histogram;
402
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
403
6
  args.GetReturnValue().Set(histogram->Mean());
404
}
405
406
static void ELDHistogramExceeds(const FunctionCallbackInfo<Value>& args) {
407
  ELDHistogram* histogram;
408
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
409
  double value = static_cast<double>(histogram->Exceeds());
410
  args.GetReturnValue().Set(value);
411
}
412
413
2
static void ELDHistogramStddev(const FunctionCallbackInfo<Value>& args) {
414
  ELDHistogram* histogram;
415
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
416
6
  args.GetReturnValue().Set(histogram->Stddev());
417
}
418
419
991
static void ELDHistogramPercentile(const FunctionCallbackInfo<Value>& args) {
420
  ELDHistogram* histogram;
421
1982
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
422
1982
  CHECK(args[0]->IsNumber());
423
2973
  double percentile = args[0].As<Number>()->Value();
424
2973
  args.GetReturnValue().Set(histogram->Percentile(percentile));
425
}
426
427
2
static void ELDHistogramPercentiles(const FunctionCallbackInfo<Value>& args) {
428
2
  Environment* env = Environment::GetCurrent(args);
429
  ELDHistogram* histogram;
430
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
431
4
  CHECK(args[0]->IsMap());
432
4
  Local<Map> map = args[0].As<Map>();
433
13
  histogram->Percentiles([&](double key, double value) {
434
    map->Set(env->context(),
435
             Number::New(env->isolate(), key),
436
65
             Number::New(env->isolate(), value)).IsEmpty();
437
15
  });
438
}
439
440
3
static void ELDHistogramEnable(const FunctionCallbackInfo<Value>& args) {
441
  ELDHistogram* histogram;
442
6
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
443
9
  args.GetReturnValue().Set(histogram->Enable());
444
}
445
446
3
static void ELDHistogramDisable(const FunctionCallbackInfo<Value>& args) {
447
  ELDHistogram* histogram;
448
6
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
449
9
  args.GetReturnValue().Set(histogram->Disable());
450
}
451
452
2
static void ELDHistogramReset(const FunctionCallbackInfo<Value>& args) {
453
  ELDHistogram* histogram;
454
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
455
2
  histogram->ResetState();
456
}
457
458
2
static void ELDHistogramNew(const FunctionCallbackInfo<Value>& args) {
459
2
  Environment* env = Environment::GetCurrent(args);
460
2
  CHECK(args.IsConstructCall());
461
8
  int32_t resolution = args[0]->IntegerValue(env->context()).FromJust();
462
2
  CHECK_GT(resolution, 0);
463
2
  new ELDHistogram(env, args.This(), resolution);
464
2
}
465
}  // namespace
466
467
2
ELDHistogram::ELDHistogram(
468
    Environment* env,
469
    Local<Object> wrap,
470
    int32_t resolution) : BaseObject(env, wrap),
471
                          Histogram(1, 3.6e12),
472
2
                          resolution_(resolution) {
473
2
  MakeWeak();
474
2
  timer_ = new uv_timer_t();
475
2
  uv_timer_init(env->event_loop(), timer_);
476
2
  timer_->data = this;
477
2
}
478
479
2
void ELDHistogram::CloseTimer() {
480
2
  if (timer_ == nullptr)
481
2
    return;
482
483
4
  env()->CloseHandle(timer_, [](uv_timer_t* handle) { delete handle; });
484
2
  timer_ = nullptr;
485
}
486
487
6
ELDHistogram::~ELDHistogram() {
488
2
  Disable();
489
2
  CloseTimer();
490
4
}
491
492
1885
void ELDHistogramDelayInterval(uv_timer_t* req) {
493
  ELDHistogram* histogram =
494
1885
    reinterpret_cast<ELDHistogram*>(req->data);
495
1885
  histogram->RecordDelta();
496

3770
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
497
                 "min", histogram->Min());
498

3770
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
499
                 "max", histogram->Max());
500

3770
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
501
                 "mean", histogram->Mean());
502

3770
  TRACE_COUNTER1(TRACING_CATEGORY_NODE2(perf, event_loop),
503
                 "stddev", histogram->Stddev());
504
1885
}
505
506
1885
bool ELDHistogram::RecordDelta() {
507
1885
  uint64_t time = uv_hrtime();
508
1885
  bool ret = true;
509
1885
  if (prev_ > 0) {
510
1884
    int64_t delta = time - prev_;
511
1884
    if (delta > 0) {
512
1884
      ret = Record(delta);
513

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

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