GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: histogram.cc Lines: 203 227 89.4 %
Date: 2021-09-29 04:12:34 Branches: 46 92 50.0 %

Line Branch Exec Source
1
#include "histogram.h"  // NOLINT(build/include_inline)
2
#include "base_object-inl.h"
3
#include "histogram-inl.h"
4
#include "memory_tracker-inl.h"
5
#include "node_errors.h"
6
#include "node_external_reference.h"
7
8
namespace node {
9
10
using v8::BigInt;
11
using v8::FunctionCallbackInfo;
12
using v8::FunctionTemplate;
13
using v8::Local;
14
using v8::Map;
15
using v8::Number;
16
using v8::Object;
17
using v8::String;
18
using v8::Value;
19
20
8
Histogram::Histogram(int64_t lowest, int64_t highest, int figures) {
21
  hdr_histogram* histogram;
22
8
  CHECK_EQ(0, hdr_init(lowest, highest, figures, &histogram));
23
8
  histogram_.reset(histogram);
24
8
}
25
26
void Histogram::MemoryInfo(MemoryTracker* tracker) const {
27
  tracker->TrackFieldWithSize("histogram", GetMemorySize());
28
}
29
30
8
HistogramImpl::HistogramImpl(int64_t lowest, int64_t highest, int figures)
31
8
    : histogram_(new Histogram(lowest, highest, figures)) {}
32
33
2
HistogramImpl::HistogramImpl(std::shared_ptr<Histogram> histogram)
34
2
    : histogram_(std::move(histogram)) {}
35
36
5
HistogramBase::HistogramBase(
37
    Environment* env,
38
    Local<Object> wrap,
39
    int64_t lowest,
40
    int64_t highest,
41
5
    int figures)
42
    : BaseObject(env, wrap),
43
5
      HistogramImpl(lowest, highest, figures) {
44
5
  MakeWeak();
45
5
}
46
47
2
HistogramBase::HistogramBase(
48
    Environment* env,
49
    Local<Object> wrap,
50
2
    std::shared_ptr<Histogram> histogram)
51
    : BaseObject(env, wrap),
52
2
      HistogramImpl(std::move(histogram)) {
53
2
  MakeWeak();
54
2
}
55
56
void HistogramBase::MemoryInfo(MemoryTracker* tracker) const {
57
  tracker->TrackField("histogram", histogram());
58
}
59
60
6
void HistogramBase::GetMin(const FunctionCallbackInfo<Value>& args) {
61
  HistogramBase* histogram;
62
6
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
63
6
  double value = static_cast<double>((*histogram)->Min());
64
12
  args.GetReturnValue().Set(value);
65
}
66
67
9
void HistogramBase::GetMax(const FunctionCallbackInfo<Value>& args) {
68
  HistogramBase* histogram;
69
9
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
70
9
  double value = static_cast<double>((*histogram)->Max());
71
18
  args.GetReturnValue().Set(value);
72
}
73
74
4
void HistogramBase::GetMean(const FunctionCallbackInfo<Value>& args) {
75
  HistogramBase* histogram;
76
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
77
8
  args.GetReturnValue().Set((*histogram)->Mean());
78
}
79
80
4
void HistogramBase::GetExceeds(const FunctionCallbackInfo<Value>& args) {
81
  HistogramBase* histogram;
82
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
83
4
  double value = static_cast<double>((*histogram)->Exceeds());
84
8
  args.GetReturnValue().Set(value);
85
}
86
87
4
void HistogramBase::GetStddev(const FunctionCallbackInfo<Value>& args) {
88
  HistogramBase* histogram;
89
4
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
90
8
  args.GetReturnValue().Set((*histogram)->Stddev());
91
}
92
93
2
void HistogramBase::GetPercentile(const FunctionCallbackInfo<Value>& args) {
94
  HistogramBase* histogram;
95
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
96
2
  CHECK(args[0]->IsNumber());
97
4
  double percentile = args[0].As<Number>()->Value();
98
4
  args.GetReturnValue().Set((*histogram)->Percentile(percentile));
99
}
100
101
1
void HistogramBase::GetPercentiles(const FunctionCallbackInfo<Value>& args) {
102
1
  Environment* env = Environment::GetCurrent(args);
103
  HistogramBase* histogram;
104
1
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
105
1
  CHECK(args[0]->IsMap());
106
1
  Local<Map> map = args[0].As<Map>();
107
1
  (*histogram)->Percentiles([map, env](double key, double value) {
108
1
    map->Set(
109
        env->context(),
110
        Number::New(env->isolate(), key),
111
3
        Number::New(env->isolate(), value)).IsEmpty();
112
1
  });
113
}
114
115
void HistogramBase::DoReset(const FunctionCallbackInfo<Value>& args) {
116
  HistogramBase* histogram;
117
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
118
  (*histogram)->Reset();
119
}
120
121
1
void HistogramBase::RecordDelta(const FunctionCallbackInfo<Value>& args) {
122
  HistogramBase* histogram;
123
1
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
124
1
  (*histogram)->RecordDelta();
125
}
126
127
22
void HistogramBase::Record(const FunctionCallbackInfo<Value>& args) {
128
22
  Environment* env = Environment::GetCurrent(args);
129

23
  CHECK_IMPLIES(!args[0]->IsNumber(), args[0]->IsBigInt());
130
22
  bool lossless = true;
131
22
  int64_t value = args[0]->IsBigInt()
132
45
      ? args[0].As<BigInt>()->Int64Value(&lossless)
133
42
      : static_cast<int64_t>(args[0].As<Number>()->Value());
134

22
  if (!lossless || value < 1)
135
    return THROW_ERR_OUT_OF_RANGE(env, "value is out of range");
136
  HistogramBase* histogram;
137
22
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
138
22
  (*histogram)->Record(value);
139
}
140
141
BaseObjectPtr<HistogramBase> HistogramBase::Create(
142
    Environment* env,
143
    int64_t lowest,
144
    int64_t highest,
145
    int figures) {
146
  Local<Object> obj;
147
  if (!GetConstructorTemplate(env)
148
          ->InstanceTemplate()
149
          ->NewInstance(env->context()).ToLocal(&obj)) {
150
    return BaseObjectPtr<HistogramBase>();
151
  }
152
153
  return MakeBaseObject<HistogramBase>(
154
      env, obj, lowest, highest, figures);
155
}
156
157
2
BaseObjectPtr<HistogramBase> HistogramBase::Create(
158
    Environment* env,
159
    std::shared_ptr<Histogram> histogram) {
160
  Local<Object> obj;
161
2
  if (!GetConstructorTemplate(env)
162
2
          ->InstanceTemplate()
163
4
          ->NewInstance(env->context()).ToLocal(&obj)) {
164
    return BaseObjectPtr<HistogramBase>();
165
  }
166
2
  return MakeBaseObject<HistogramBase>(env, obj, std::move(histogram));
167
}
168
169
5
void HistogramBase::New(const FunctionCallbackInfo<Value>& args) {
170
5
  CHECK(args.IsConstructCall());
171
5
  Environment* env = Environment::GetCurrent(args);
172
5
  new HistogramBase(env, args.This());
173
5
}
174
175
620
Local<FunctionTemplate> HistogramBase::GetConstructorTemplate(
176
    Environment* env) {
177
620
  Local<FunctionTemplate> tmpl = env->histogram_ctor_template();
178
620
  if (tmpl.IsEmpty()) {
179
618
    tmpl = env->NewFunctionTemplate(New);
180
    Local<String> classname =
181
618
        FIXED_ONE_BYTE_STRING(env->isolate(), "Histogram");
182
618
    tmpl->SetClassName(classname);
183
618
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
184
185
1236
    tmpl->InstanceTemplate()->SetInternalFieldCount(
186
        HistogramBase::kInternalFieldCount);
187
618
    env->SetProtoMethodNoSideEffect(tmpl, "exceeds", GetExceeds);
188
618
    env->SetProtoMethodNoSideEffect(tmpl, "min", GetMin);
189
618
    env->SetProtoMethodNoSideEffect(tmpl, "max", GetMax);
190
618
    env->SetProtoMethodNoSideEffect(tmpl, "mean", GetMean);
191
618
    env->SetProtoMethodNoSideEffect(tmpl, "stddev", GetStddev);
192
618
    env->SetProtoMethodNoSideEffect(tmpl, "percentile", GetPercentile);
193
618
    env->SetProtoMethodNoSideEffect(tmpl, "percentiles", GetPercentiles);
194
618
    env->SetProtoMethod(tmpl, "reset", DoReset);
195
618
    env->SetProtoMethod(tmpl, "record", Record);
196
618
    env->SetProtoMethod(tmpl, "recordDelta", RecordDelta);
197
618
    env->set_histogram_ctor_template(tmpl);
198
  }
199
620
  return tmpl;
200
}
201
202
4855
void HistogramBase::RegisterExternalReferences(
203
    ExternalReferenceRegistry* registry) {
204
4855
  registry->Register(New);
205
4855
  registry->Register(GetExceeds);
206
4855
  registry->Register(GetMin);
207
4855
  registry->Register(GetMax);
208
4855
  registry->Register(GetMean);
209
4855
  registry->Register(GetStddev);
210
4855
  registry->Register(GetPercentile);
211
4855
  registry->Register(GetPercentiles);
212
4855
  registry->Register(DoReset);
213
4855
  registry->Register(Record);
214
4855
  registry->Register(RecordDelta);
215
4855
}
216
217
618
void HistogramBase::Initialize(Environment* env, Local<Object> target) {
218
618
  env->SetConstructorFunction(target, "Histogram", GetConstructorTemplate(env));
219
618
}
220
221
2
BaseObjectPtr<BaseObject> HistogramBase::HistogramTransferData::Deserialize(
222
    Environment* env,
223
    v8::Local<v8::Context> context,
224
    std::unique_ptr<worker::TransferData> self) {
225
2
  return Create(env, std::move(histogram_));
226
}
227
228
1
std::unique_ptr<worker::TransferData> HistogramBase::CloneForMessaging() const {
229
1
  return std::make_unique<HistogramTransferData>(this);
230
}
231
232
void HistogramBase::HistogramTransferData::MemoryInfo(
233
    MemoryTracker* tracker) const {
234
  tracker->TrackField("histogram", histogram_);
235
}
236
237
618
Local<FunctionTemplate> IntervalHistogram::GetConstructorTemplate(
238
    Environment* env) {
239
618
  Local<FunctionTemplate> tmpl = env->intervalhistogram_constructor_template();
240
618
  if (tmpl.IsEmpty()) {
241
618
    tmpl = FunctionTemplate::New(env->isolate());
242
618
    tmpl->Inherit(HandleWrap::GetConstructorTemplate(env));
243
1236
    tmpl->InstanceTemplate()->SetInternalFieldCount(
244
        HistogramBase::kInternalFieldCount);
245
618
    env->SetProtoMethodNoSideEffect(tmpl, "exceeds", GetExceeds);
246
618
    env->SetProtoMethodNoSideEffect(tmpl, "min", GetMin);
247
618
    env->SetProtoMethodNoSideEffect(tmpl, "max", GetMax);
248
618
    env->SetProtoMethodNoSideEffect(tmpl, "mean", GetMean);
249
618
    env->SetProtoMethodNoSideEffect(tmpl, "stddev", GetStddev);
250
618
    env->SetProtoMethodNoSideEffect(tmpl, "percentile", GetPercentile);
251
618
    env->SetProtoMethodNoSideEffect(tmpl, "percentiles", GetPercentiles);
252
618
    env->SetProtoMethod(tmpl, "reset", DoReset);
253
618
    env->SetProtoMethod(tmpl, "start", Start);
254
618
    env->SetProtoMethod(tmpl, "stop", Stop);
255
618
    env->set_intervalhistogram_constructor_template(tmpl);
256
  }
257
618
  return tmpl;
258
}
259
260
4855
void IntervalHistogram::RegisterExternalReferences(
261
    ExternalReferenceRegistry* registry) {
262
4855
  registry->Register(GetExceeds);
263
4855
  registry->Register(GetMin);
264
4855
  registry->Register(GetMax);
265
4855
  registry->Register(GetMean);
266
4855
  registry->Register(GetStddev);
267
4855
  registry->Register(GetPercentile);
268
4855
  registry->Register(GetPercentiles);
269
4855
  registry->Register(DoReset);
270
4855
  registry->Register(Start);
271
4855
  registry->Register(Stop);
272
4855
}
273
274
3
IntervalHistogram::IntervalHistogram(
275
    Environment* env,
276
    Local<Object> wrap,
277
    AsyncWrap::ProviderType type,
278
    int32_t interval,
279
    int64_t lowest,
280
    int64_t highest,
281
3
    int figures)
282
    : HandleWrap(
283
          env,
284
          wrap,
285
3
          reinterpret_cast<uv_handle_t*>(&timer_),
286
          type),
287
      HistogramImpl(lowest, highest, figures),
288
3
      interval_(interval) {
289
3
  MakeWeak();
290
3
  uv_timer_init(env->event_loop(), &timer_);
291
3
}
292
293
1766
void IntervalHistogram::TimerCB(uv_timer_t* handle) {
294
  IntervalHistogram* histogram =
295
1766
      ContainerOf(&IntervalHistogram::timer_, handle);
296
1766
  histogram->OnInterval();
297
1766
}
298
299
void IntervalHistogram::MemoryInfo(MemoryTracker* tracker) const {
300
  tracker->TrackField("histogram", histogram());
301
}
302
303
3
void IntervalHistogram::OnStart(StartFlags flags) {
304

3
  if (enabled_ || IsHandleClosing()) return;
305
3
  enabled_ = true;
306
3
  if (flags == StartFlags::RESET)
307
    histogram()->Reset();
308
3
  uv_timer_start(&timer_, TimerCB, interval_, interval_);
309
3
  uv_unref(reinterpret_cast<uv_handle_t*>(&timer_));
310
}
311
312
2
void IntervalHistogram::OnStop() {
313

2
  if (!enabled_ || IsHandleClosing()) return;
314
2
  enabled_ = false;
315
2
  uv_timer_stop(&timer_);
316
}
317
318
3
void IntervalHistogram::Start(const FunctionCallbackInfo<Value>& args) {
319
  IntervalHistogram* histogram;
320
3
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
321

6
  histogram->OnStart(args[0]->IsTrue() ? StartFlags::RESET : StartFlags::NONE);
322
}
323
324
2
void IntervalHistogram::Stop(const FunctionCallbackInfo<Value>& args) {
325
  IntervalHistogram* histogram;
326
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
327
2
  histogram->OnStop();
328
}
329
330
2
void IntervalHistogram::GetMin(const FunctionCallbackInfo<Value>& args) {
331
  IntervalHistogram* histogram;
332
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
333
2
  double value = static_cast<double>((*histogram)->Min());
334
4
  args.GetReturnValue().Set(value);
335
}
336
337
2
void IntervalHistogram::GetMax(const FunctionCallbackInfo<Value>& args) {
338
  IntervalHistogram* histogram;
339
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
340
2
  double value = static_cast<double>((*histogram)->Max());
341
4
  args.GetReturnValue().Set(value);
342
}
343
344
2
void IntervalHistogram::GetMean(const FunctionCallbackInfo<Value>& args) {
345
  IntervalHistogram* histogram;
346
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
347
4
  args.GetReturnValue().Set((*histogram)->Mean());
348
}
349
350
void IntervalHistogram::GetExceeds(const FunctionCallbackInfo<Value>& args) {
351
  IntervalHistogram* histogram;
352
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
353
  double value = static_cast<double>((*histogram)->Exceeds());
354
  args.GetReturnValue().Set(value);
355
}
356
357
2
void IntervalHistogram::GetStddev(const FunctionCallbackInfo<Value>& args) {
358
  IntervalHistogram* histogram;
359
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
360
4
  args.GetReturnValue().Set((*histogram)->Stddev());
361
}
362
363
991
void IntervalHistogram::GetPercentile(const FunctionCallbackInfo<Value>& args) {
364
  IntervalHistogram* histogram;
365
991
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
366
991
  CHECK(args[0]->IsNumber());
367
1982
  double percentile = args[0].As<Number>()->Value();
368
1982
  args.GetReturnValue().Set((*histogram)->Percentile(percentile));
369
}
370
371
2
void IntervalHistogram::GetPercentiles(
372
    const FunctionCallbackInfo<Value>& args) {
373
2
  Environment* env = Environment::GetCurrent(args);
374
  IntervalHistogram* histogram;
375
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
376
2
  CHECK(args[0]->IsMap());
377
2
  Local<Map> map = args[0].As<Map>();
378
2
  (*histogram)->Percentiles([map, env](double key, double value) {
379
14
    map->Set(
380
        env->context(),
381
        Number::New(env->isolate(), key),
382
42
        Number::New(env->isolate(), value)).IsEmpty();
383
14
  });
384
}
385
386
2
void IntervalHistogram::DoReset(const FunctionCallbackInfo<Value>& args) {
387
  IntervalHistogram* histogram;
388
2
  ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder());
389
2
  (*histogram)->Reset();
390
}
391
392
std::unique_ptr<worker::TransferData>
393
1
IntervalHistogram::CloneForMessaging() const {
394
1
  return std::make_unique<HistogramBase::HistogramTransferData>(histogram());
395
}
396
397
}  // namespace node