diff options
author | James M Snell <jasnell@gmail.com> | 2021-12-12 03:59:48 +0300 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2021-12-19 20:56:36 +0300 |
commit | 23637e9a3b208892449268290143dad4391fee45 (patch) | |
tree | c8f83283bb0d357b7db22298e217cbe5e877a656 /src/histogram.cc | |
parent | 665b404e6512c6fdfe811e793d4f14bf8f8a7d36 (diff) |
perf_hooks: multiple fixes for Histogram
* The createHistogram(options) options weren't actually implemented
* Add a new count property that tracks the number of samples
* Adds BigInt options for relevant properties
* Adds add(other) method for RecordableHistogram
* Cleans up and expands tests
* Eliminates unnecessary ELDHistogram native class
* Improve/Simplify histogram transfer impl
Signed-off-by: James M Snell <jasnell@gmail.com>
perf_hooks: simplify Histogram constructor options
Signed-off-by: James M Snell <jasnell@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/41153
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/histogram.cc')
-rw-r--r-- | src/histogram.cc | 280 |
1 files changed, 254 insertions, 26 deletions
diff --git a/src/histogram.cc b/src/histogram.cc index 6fbb0eda6c0..87641a4a369 100644 --- a/src/histogram.cc +++ b/src/histogram.cc @@ -10,16 +10,21 @@ namespace node { using v8::BigInt; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; +using v8::Integer; using v8::Local; using v8::Map; using v8::Number; using v8::Object; using v8::String; +using v8::Uint32; using v8::Value; -Histogram::Histogram(int64_t lowest, int64_t highest, int figures) { +Histogram::Histogram(const Options& options) { hdr_histogram* histogram; - CHECK_EQ(0, hdr_init(lowest, highest, figures, &histogram)); + CHECK_EQ(0, hdr_init(options.lowest, + options.highest, + options.figures, + &histogram)); histogram_.reset(histogram); } @@ -27,8 +32,8 @@ void Histogram::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackFieldWithSize("histogram", GetMemorySize()); } -HistogramImpl::HistogramImpl(int64_t lowest, int64_t highest, int figures) - : histogram_(new Histogram(lowest, highest, figures)) {} +HistogramImpl::HistogramImpl(const Histogram::Options& options) + : histogram_(new Histogram(options)) {} HistogramImpl::HistogramImpl(std::shared_ptr<Histogram> histogram) : histogram_(std::move(histogram)) {} @@ -36,11 +41,9 @@ HistogramImpl::HistogramImpl(std::shared_ptr<Histogram> histogram) HistogramBase::HistogramBase( Environment* env, Local<Object> wrap, - int64_t lowest, - int64_t highest, - int figures) + const Histogram::Options& options) : BaseObject(env, wrap), - HistogramImpl(lowest, highest, figures) { + HistogramImpl(options) { MakeWeak(); } @@ -57,6 +60,22 @@ void HistogramBase::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackField("histogram", histogram()); } +void HistogramBase::GetCount(const v8::FunctionCallbackInfo<v8::Value>& args) { + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + double value = static_cast<double>((*histogram)->Count()); + args.GetReturnValue().Set(value); +} + +void HistogramBase::GetCountBigInt( + const v8::FunctionCallbackInfo<v8::Value>& args) { + Environment* env = Environment::GetCurrent(args); + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set( + BigInt::NewFromUnsigned(env->isolate(), (*histogram)->Count())); +} + void HistogramBase::GetMin(const FunctionCallbackInfo<Value>& args) { HistogramBase* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -64,6 +83,13 @@ void HistogramBase::GetMin(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(value); } +void HistogramBase::GetMinBigInt(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set(BigInt::New(env->isolate(), (*histogram)->Min())); +} + void HistogramBase::GetMax(const FunctionCallbackInfo<Value>& args) { HistogramBase* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -71,6 +97,14 @@ void HistogramBase::GetMax(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(value); } +void HistogramBase::GetMaxBigInt(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set( + BigInt::New(env->isolate(), (*histogram)->Max())); +} + void HistogramBase::GetMean(const FunctionCallbackInfo<Value>& args) { HistogramBase* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -84,6 +118,14 @@ void HistogramBase::GetExceeds(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(value); } +void HistogramBase::GetExceedsBigInt(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set( + BigInt::NewFromUnsigned(env->isolate(), (*histogram)->Exceeds())); +} + void HistogramBase::GetStddev(const FunctionCallbackInfo<Value>& args) { HistogramBase* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -95,7 +137,19 @@ void HistogramBase::GetPercentile(const FunctionCallbackInfo<Value>& args) { ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); CHECK(args[0]->IsNumber()); double percentile = args[0].As<Number>()->Value(); - args.GetReturnValue().Set((*histogram)->Percentile(percentile)); + double value = static_cast<double>((*histogram)->Percentile(percentile)); + args.GetReturnValue().Set(value); +} + +void HistogramBase::GetPercentileBigInt( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + CHECK(args[0]->IsNumber()); + double percentile = args[0].As<Number>()->Value(); + int64_t value = (*histogram)->Percentile(percentile); + args.GetReturnValue().Set(BigInt::New(env->isolate(), value)); } void HistogramBase::GetPercentiles(const FunctionCallbackInfo<Value>& args) { @@ -104,11 +158,26 @@ void HistogramBase::GetPercentiles(const FunctionCallbackInfo<Value>& args) { 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) { + (*histogram)->Percentiles([map, env](double key, int64_t value) { + map->Set( + env->context(), + Number::New(env->isolate(), key), + Number::New(env->isolate(), static_cast<double>(value))).IsEmpty(); + }); +} + +void HistogramBase::GetPercentilesBigInt( + 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, int64_t value) { map->Set( env->context(), Number::New(env->isolate(), key), - Number::New(env->isolate(), value)).IsEmpty(); + BigInt::New(env->isolate(), value)).IsEmpty(); }); } @@ -138,11 +207,22 @@ void HistogramBase::Record(const FunctionCallbackInfo<Value>& args) { (*histogram)->Record(value); } +void HistogramBase::Add(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + HistogramBase* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + + CHECK(GetConstructorTemplate(env)->HasInstance(args[0])); + HistogramBase* other; + ASSIGN_OR_RETURN_UNWRAP(&other, args[0]); + + double count = (*histogram)->Add(*(other->histogram())); + args.GetReturnValue().Set(count); +} + BaseObjectPtr<HistogramBase> HistogramBase::Create( Environment* env, - int64_t lowest, - int64_t highest, - int figures) { + const Histogram::Options& options) { Local<Object> obj; if (!GetConstructorTemplate(env) ->InstanceTemplate() @@ -150,8 +230,7 @@ BaseObjectPtr<HistogramBase> HistogramBase::Create( return BaseObjectPtr<HistogramBase>(); } - return MakeBaseObject<HistogramBase>( - env, obj, lowest, highest, figures); + return MakeBaseObject<HistogramBase>(env, obj, options); } BaseObjectPtr<HistogramBase> HistogramBase::Create( @@ -169,7 +248,32 @@ BaseObjectPtr<HistogramBase> HistogramBase::Create( void HistogramBase::New(const FunctionCallbackInfo<Value>& args) { CHECK(args.IsConstructCall()); Environment* env = Environment::GetCurrent(args); - new HistogramBase(env, args.This()); + + CHECK_IMPLIES(!args[0]->IsNumber(), args[0]->IsBigInt()); + CHECK_IMPLIES(!args[1]->IsNumber(), args[1]->IsBigInt()); + CHECK(args[2]->IsUint32()); + + int64_t lowest = 1; + int64_t highest = std::numeric_limits<int64_t>::max(); + + bool lossless_ignored; + + if (args[0]->IsNumber()) { + lowest = args[0].As<Integer>()->Value(); + } else if (args[0]->IsBigInt()) { + lowest = args[0].As<BigInt>()->Int64Value(&lossless_ignored); + } + + if (args[1]->IsNumber()) { + highest = args[1].As<Integer>()->Value(); + } else if (args[1]->IsBigInt()) { + highest = args[1].As<BigInt>()->Int64Value(&lossless_ignored); + } + + int32_t figures = args[2].As<Uint32>()->Value(); + new HistogramBase(env, args.This(), Histogram::Options { + lowest, highest, figures + }); } Local<FunctionTemplate> HistogramBase::GetConstructorTemplate( @@ -184,16 +288,26 @@ Local<FunctionTemplate> HistogramBase::GetConstructorTemplate( tmpl->InstanceTemplate()->SetInternalFieldCount( HistogramBase::kInternalFieldCount); + env->SetProtoMethodNoSideEffect(tmpl, "count", GetCount); + env->SetProtoMethodNoSideEffect(tmpl, "countBigInt", GetCountBigInt); env->SetProtoMethodNoSideEffect(tmpl, "exceeds", GetExceeds); + env->SetProtoMethodNoSideEffect(tmpl, "exceedsBigInt", GetExceedsBigInt); env->SetProtoMethodNoSideEffect(tmpl, "min", GetMin); + env->SetProtoMethodNoSideEffect(tmpl, "minBigInt", GetMinBigInt); env->SetProtoMethodNoSideEffect(tmpl, "max", GetMax); + env->SetProtoMethodNoSideEffect(tmpl, "maxBigInt", GetMaxBigInt); env->SetProtoMethodNoSideEffect(tmpl, "mean", GetMean); env->SetProtoMethodNoSideEffect(tmpl, "stddev", GetStddev); env->SetProtoMethodNoSideEffect(tmpl, "percentile", GetPercentile); + env->SetProtoMethodNoSideEffect(tmpl, "percentileBigInt", + GetPercentileBigInt); env->SetProtoMethodNoSideEffect(tmpl, "percentiles", GetPercentiles); + env->SetProtoMethodNoSideEffect(tmpl, "percentilesBigInt", + GetPercentilesBigInt); env->SetProtoMethod(tmpl, "reset", DoReset); env->SetProtoMethod(tmpl, "record", Record); env->SetProtoMethod(tmpl, "recordDelta", RecordDelta); + env->SetProtoMethod(tmpl, "add", Add); env->set_histogram_ctor_template(tmpl); } return tmpl; @@ -202,16 +316,24 @@ Local<FunctionTemplate> HistogramBase::GetConstructorTemplate( void HistogramBase::RegisterExternalReferences( ExternalReferenceRegistry* registry) { registry->Register(New); + registry->Register(GetCount); + registry->Register(GetCountBigInt); registry->Register(GetExceeds); + registry->Register(GetExceedsBigInt); registry->Register(GetMin); + registry->Register(GetMinBigInt); registry->Register(GetMax); + registry->Register(GetMaxBigInt); registry->Register(GetMean); registry->Register(GetStddev); registry->Register(GetPercentile); + registry->Register(GetPercentileBigInt); registry->Register(GetPercentiles); + registry->Register(GetPercentilesBigInt); registry->Register(DoReset); registry->Register(Record); registry->Register(RecordDelta); + registry->Register(Add); } void HistogramBase::Initialize(Environment* env, Local<Object> target) { @@ -242,13 +364,22 @@ Local<FunctionTemplate> IntervalHistogram::GetConstructorTemplate( tmpl->Inherit(HandleWrap::GetConstructorTemplate(env)); tmpl->InstanceTemplate()->SetInternalFieldCount( HistogramBase::kInternalFieldCount); + env->SetProtoMethodNoSideEffect(tmpl, "count", GetCount); + env->SetProtoMethodNoSideEffect(tmpl, "countBigInt", GetCountBigInt); env->SetProtoMethodNoSideEffect(tmpl, "exceeds", GetExceeds); + env->SetProtoMethodNoSideEffect(tmpl, "exceedsBigInt", GetExceedsBigInt); env->SetProtoMethodNoSideEffect(tmpl, "min", GetMin); + env->SetProtoMethodNoSideEffect(tmpl, "minBigInt", GetMinBigInt); env->SetProtoMethodNoSideEffect(tmpl, "max", GetMax); + env->SetProtoMethodNoSideEffect(tmpl, "maxBigInt", GetMaxBigInt); env->SetProtoMethodNoSideEffect(tmpl, "mean", GetMean); env->SetProtoMethodNoSideEffect(tmpl, "stddev", GetStddev); env->SetProtoMethodNoSideEffect(tmpl, "percentile", GetPercentile); + env->SetProtoMethodNoSideEffect(tmpl, "percentileBigInt", + GetPercentileBigInt); env->SetProtoMethodNoSideEffect(tmpl, "percentiles", GetPercentiles); + env->SetProtoMethodNoSideEffect(tmpl, "percentilesBigInt", + GetPercentilesBigInt); env->SetProtoMethod(tmpl, "reset", DoReset); env->SetProtoMethod(tmpl, "start", Start); env->SetProtoMethod(tmpl, "stop", Stop); @@ -259,13 +390,20 @@ Local<FunctionTemplate> IntervalHistogram::GetConstructorTemplate( void IntervalHistogram::RegisterExternalReferences( ExternalReferenceRegistry* registry) { + registry->Register(GetCount); + registry->Register(GetCountBigInt); registry->Register(GetExceeds); + registry->Register(GetExceedsBigInt); registry->Register(GetMin); + registry->Register(GetMinBigInt); registry->Register(GetMax); + registry->Register(GetMaxBigInt); registry->Register(GetMean); registry->Register(GetStddev); registry->Register(GetPercentile); + registry->Register(GetPercentileBigInt); registry->Register(GetPercentiles); + registry->Register(GetPercentilesBigInt); registry->Register(DoReset); registry->Register(Start); registry->Register(Stop); @@ -276,24 +414,48 @@ IntervalHistogram::IntervalHistogram( Local<Object> wrap, AsyncWrap::ProviderType type, int32_t interval, - int64_t lowest, - int64_t highest, - int figures) + std::function<void(Histogram&)> on_interval, + const Histogram::Options& options) : HandleWrap( env, wrap, reinterpret_cast<uv_handle_t*>(&timer_), type), - HistogramImpl(lowest, highest, figures), - interval_(interval) { + HistogramImpl(options), + interval_(interval), + on_interval_(std::move(on_interval)) { MakeWeak(); uv_timer_init(env->event_loop(), &timer_); } +BaseObjectPtr<IntervalHistogram> IntervalHistogram::Create( + Environment* env, + int32_t interval, + std::function<void(Histogram&)> on_interval, + const Histogram::Options& options) { + Local<Object> obj; + if (!GetConstructorTemplate(env) + ->InstanceTemplate() + ->NewInstance(env->context()).ToLocal(&obj)) { + return BaseObjectPtr<IntervalHistogram>(); + } + + return MakeBaseObject<IntervalHistogram>( + env, + obj, + AsyncWrap::PROVIDER_ELDHISTOGRAM, + interval, + std::move(on_interval), + options); +} + void IntervalHistogram::TimerCB(uv_timer_t* handle) { IntervalHistogram* histogram = ContainerOf(&IntervalHistogram::timer_, handle); - histogram->OnInterval(); + + Histogram* h = histogram->histogram().get(); + + histogram->on_interval_(*h); } void IntervalHistogram::MemoryInfo(MemoryTracker* tracker) const { @@ -327,6 +489,22 @@ void IntervalHistogram::Stop(const FunctionCallbackInfo<Value>& args) { histogram->OnStop(); } +void IntervalHistogram::GetCount(const FunctionCallbackInfo<Value>& args) { + IntervalHistogram* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + double value = static_cast<double>((*histogram)->Count()); + args.GetReturnValue().Set(value); +} + +void IntervalHistogram::GetCountBigInt( + const v8::FunctionCallbackInfo<v8::Value>& args) { + Environment* env = Environment::GetCurrent(args); + IntervalHistogram* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set( + BigInt::NewFromUnsigned(env->isolate(), (*histogram)->Count())); +} + void IntervalHistogram::GetMin(const FunctionCallbackInfo<Value>& args) { IntervalHistogram* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -334,6 +512,13 @@ void IntervalHistogram::GetMin(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(value); } +void IntervalHistogram::GetMinBigInt(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + IntervalHistogram* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set(BigInt::New(env->isolate(), (*histogram)->Min())); +} + void IntervalHistogram::GetMax(const FunctionCallbackInfo<Value>& args) { IntervalHistogram* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -341,6 +526,13 @@ void IntervalHistogram::GetMax(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(value); } +void IntervalHistogram::GetMaxBigInt(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + IntervalHistogram* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set(BigInt::New(env->isolate(), (*histogram)->Min())); +} + void IntervalHistogram::GetMean(const FunctionCallbackInfo<Value>& args) { IntervalHistogram* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -354,6 +546,15 @@ void IntervalHistogram::GetExceeds(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(value); } +void IntervalHistogram::GetExceedsBigInt( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + IntervalHistogram* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + args.GetReturnValue().Set( + BigInt::New(env->isolate(), (*histogram)->Exceeds())); +} + void IntervalHistogram::GetStddev(const FunctionCallbackInfo<Value>& args) { IntervalHistogram* histogram; ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); @@ -365,7 +566,19 @@ void IntervalHistogram::GetPercentile(const FunctionCallbackInfo<Value>& args) { ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); CHECK(args[0]->IsNumber()); double percentile = args[0].As<Number>()->Value(); - args.GetReturnValue().Set((*histogram)->Percentile(percentile)); + double value = static_cast<double>((*histogram)->Percentile(percentile)); + args.GetReturnValue().Set(value); +} + +void IntervalHistogram::GetPercentileBigInt( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + IntervalHistogram* histogram; + ASSIGN_OR_RETURN_UNWRAP(&histogram, args.Holder()); + CHECK(args[0]->IsNumber()); + double percentile = args[0].As<Number>()->Value(); + int64_t value = (*histogram)->Percentile(percentile); + args.GetReturnValue().Set(BigInt::New(env->isolate(), value)); } void IntervalHistogram::GetPercentiles( @@ -375,11 +588,26 @@ void IntervalHistogram::GetPercentiles( 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) { + (*histogram)->Percentiles([map, env](double key, int64_t value) { + map->Set( + env->context(), + Number::New(env->isolate(), key), + Number::New(env->isolate(), static_cast<double>(value))).IsEmpty(); + }); +} + +void IntervalHistogram::GetPercentilesBigInt( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + IntervalHistogram* 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, int64_t value) { map->Set( env->context(), Number::New(env->isolate(), key), - Number::New(env->isolate(), value)).IsEmpty(); + BigInt::New(env->isolate(), value)).IsEmpty(); }); } |