diff options
author | James M Snell <jasnell@gmail.com> | 2020-02-28 00:14:38 +0300 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2020-03-05 00:30:10 +0300 |
commit | 6b44df24153aa9a6694c24a2fae2f30e0eff3129 (patch) | |
tree | 5c0fcd298696ed6e5bbf52ab0096f0ef5338c9df /src/histogram.cc | |
parent | 4d5318c16467623770bb77f7ecac720cb93b0326 (diff) |
perf,src: add HistogramBase and internal/histogram.js
Separating this out from the QUIC PR to allow it to be separately
reviewed. The QUIC implementation makes use of the hdr_histogram
for dynamic performance monitoring. This introduces a BaseObject
class that allows the internal histograms to be accessed on the
JavaScript side and adds a generic Histogram class that will be
used by both QUIC and perf_hooks (for the event loop delay
monitoring).
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/31988
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/histogram.cc')
-rw-r--r-- | src/histogram.cc | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/histogram.cc b/src/histogram.cc new file mode 100644 index 00000000000..8d1eb77b1bc --- /dev/null +++ b/src/histogram.cc @@ -0,0 +1,141 @@ +#include "histogram.h" // NOLINT(build/include_inline) +#include "histogram-inl.h" +#include "memory_tracker-inl.h" + +namespace node { + +using v8::FunctionCallbackInfo; +using v8::FunctionTemplate; +using v8::Local; +using v8::Map; +using v8::Number; +using v8::ObjectTemplate; +using v8::String; +using v8::Value; + +Histogram::Histogram(int64_t lowest, int64_t highest, int figures) { + hdr_histogram* histogram; + CHECK_EQ(0, hdr_init(lowest, highest, figures, &histogram)); + histogram_.reset(histogram); +} + +HistogramBase::HistogramBase( + Environment* env, + v8::Local<v8::Object> wrap, + int64_t lowest, + int64_t highest, + int figures) + : BaseObject(env, wrap), + Histogram(lowest, highest, figures) { + MakeWeak(); +} + +void HistogramBase::MemoryInfo(MemoryTracker* tracker) const { + tracker->TrackFieldWithSize("histogram", GetMemorySize()); +} + +void HistogramBase::GetMin(const FunctionCallbackInfo<Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + double value = static_cast<double>(histogram->Min()); + args.GetReturnValue().Set(value); +} + +void HistogramBase::GetMax(const FunctionCallbackInfo<Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + double value = static_cast<double>(histogram->Max()); + args.GetReturnValue().Set(value); +} + +void HistogramBase::GetMean(const FunctionCallbackInfo<Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set(histogram->Mean()); +} + +void HistogramBase::GetExceeds(const FunctionCallbackInfo<Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + double value = static_cast<double>(histogram->Exceeds()); + args.GetReturnValue().Set(value); +} + +void HistogramBase::GetStddev(const FunctionCallbackInfo<Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set(histogram->Stddev()); +} + +void HistogramBase::GetPercentile( + const FunctionCallbackInfo<Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + CHECK(args[0]->IsNumber()); + double percentile = args[0].As<Number>()->Value(); + args.GetReturnValue().Set(histogram->Percentile(percentile)); +} + +void HistogramBase::GetPercentiles( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + CHECK(args[0]->IsMap()); + Local<Map> map = args[0].As<Map>(); + histogram->Percentiles([map, env](double key, double value) { + map->Set( + env->context(), + Number::New(env->isolate(), key), + Number::New(env->isolate(), value)).IsEmpty(); + }); +} + +void HistogramBase::DoReset(const FunctionCallbackInfo<Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + histogram->ResetState(); +} + +BaseObjectPtr<HistogramBase> HistogramBase::New( + Environment* env, + int64_t lowest, + int64_t highest, + int figures) { + CHECK_LE(lowest, highest); + CHECK_GT(figures, 0); + v8::Local<v8::Object> obj; + auto tmpl = env->histogram_instance_template(); + if (!tmpl->NewInstance(env->context()).ToLocal(&obj)) + return {}; + + return MakeDetachedBaseObject<HistogramBase>( + env, obj, lowest, highest, figures); +} + +void HistogramBase::Initialize(Environment* env) { + // Guard against multiple initializations + if (!env->histogram_instance_template().IsEmpty()) + return; + + Local<FunctionTemplate> histogram = FunctionTemplate::New(env->isolate()); + Local<String> classname = FIXED_ONE_BYTE_STRING(env->isolate(), "Histogram"); + histogram->SetClassName(classname); + + Local<ObjectTemplate> histogramt = + histogram->InstanceTemplate(); + + histogramt->SetInternalFieldCount(1); + env->SetProtoMethod(histogram, "exceeds", HistogramBase::GetExceeds); + env->SetProtoMethod(histogram, "min", HistogramBase::GetMin); + env->SetProtoMethod(histogram, "max", HistogramBase::GetMax); + env->SetProtoMethod(histogram, "mean", HistogramBase::GetMean); + env->SetProtoMethod(histogram, "stddev", HistogramBase::GetStddev); + env->SetProtoMethod(histogram, "percentile", HistogramBase::GetPercentile); + env->SetProtoMethod(histogram, "percentiles", HistogramBase::GetPercentiles); + env->SetProtoMethod(histogram, "reset", HistogramBase::DoReset); + + env->set_histogram_instance_template(histogramt); +} + +} // namespace node |