@@ -68,6 +68,10 @@ CFunction IntervalHistogram::fast_start_(
6868 CFunction::Make (&IntervalHistogram::FastStart));
6969CFunction IntervalHistogram::fast_stop_ (
7070 CFunction::Make (&IntervalHistogram::FastStop));
71+ CFunction ELDHistogram::fast_start_ (
72+ CFunction::Make (&ELDHistogram::FastStart));
73+ CFunction ELDHistogram::fast_stop_ (
74+ CFunction::Make (&ELDHistogram::FastStop));
7175
7276void HistogramImpl::AddMethods (Isolate* isolate, Local<FunctionTemplate> tmpl) {
7377 // TODO(@jasnell): The bigint API variations do not yet support fast
@@ -444,6 +448,173 @@ void IntervalHistogram::FastStop(Local<Value> receiver) {
444448 histogram->OnStop ();
445449}
446450
451+ Local<FunctionTemplate> ELDHistogram::GetConstructorTemplate (
452+ Environment* env) {
453+ Local<FunctionTemplate> tmpl = env->eldhistogram_constructor_template ();
454+ if (tmpl.IsEmpty ()) {
455+ Isolate* isolate = env->isolate ();
456+ tmpl = NewFunctionTemplate (isolate, nullptr );
457+ tmpl->Inherit (HandleWrap::GetConstructorTemplate (env));
458+ tmpl->SetClassName (FIXED_ONE_BYTE_STRING (isolate, " Histogram" ));
459+ auto instance = tmpl->InstanceTemplate ();
460+ instance->SetInternalFieldCount (ELDHistogram::kInternalFieldCount );
461+ HistogramImpl::AddMethods (isolate, tmpl);
462+ SetFastMethod (isolate, instance, " start" , Start, &fast_start_);
463+ SetFastMethod (isolate, instance, " stop" , Stop, &fast_stop_);
464+ env->set_eldhistogram_constructor_template (tmpl);
465+ }
466+ return tmpl;
467+ }
468+
469+ void ELDHistogram::RegisterExternalReferences (
470+ ExternalReferenceRegistry* registry) {
471+ registry->Register (Start);
472+ registry->Register (Stop);
473+ registry->Register (fast_start_);
474+ registry->Register (fast_stop_);
475+ HistogramImpl::RegisterExternalReferences (registry);
476+ }
477+
478+ ELDHistogram::ELDHistogram (
479+ Environment* env,
480+ Local<Object> wrap,
481+ AsyncWrap::ProviderType type,
482+ const Histogram::Options& options)
483+ : HandleWrap(
484+ env,
485+ wrap,
486+ reinterpret_cast <uv_handle_t *>(&check_handle_),
487+ type),
488+ HistogramImpl(options) {
489+ MakeWeak ();
490+ wrap->SetAlignedPointerInInternalField (
491+ HistogramImpl::InternalFields::kImplField ,
492+ static_cast <HistogramImpl*>(this ),
493+ EmbedderDataTag::kDefault );
494+ uv_check_init (env->event_loop (), &check_handle_);
495+ uv_prepare_init (env->event_loop (), &prepare_handle_);
496+ uv_unref (reinterpret_cast <uv_handle_t *>(&check_handle_));
497+ uv_unref (reinterpret_cast <uv_handle_t *>(&prepare_handle_));
498+ prepare_handle_.data = this ;
499+ }
500+
501+ BaseObjectPtr<ELDHistogram> ELDHistogram::Create (
502+ Environment* env,
503+ const Histogram::Options& options) {
504+ Local<Object> obj;
505+ if (!GetConstructorTemplate (env)
506+ ->InstanceTemplate ()
507+ ->NewInstance (env->context ()).ToLocal (&obj)) {
508+ return nullptr ;
509+ }
510+
511+ return MakeBaseObject<ELDHistogram>(
512+ env,
513+ obj,
514+ AsyncWrap::PROVIDER_ELDHISTOGRAM,
515+ options);
516+ }
517+
518+ void ELDHistogram::PrepareCB (uv_prepare_t * handle) {
519+ ELDHistogram* self = static_cast <ELDHistogram*>(handle->data );
520+ if (!self->enabled_ ) return ;
521+ self->prepare_time_ = uv_hrtime ();
522+ self->timeout_ = uv_backend_timeout (handle->loop );
523+ }
524+
525+ void ELDHistogram::CheckCB (uv_check_t * handle) {
526+ ELDHistogram* self =
527+ ContainerOf (&ELDHistogram::check_handle_, handle);
528+ if (!self->enabled_ ) return ;
529+
530+ uint64_t check_time = uv_hrtime ();
531+ uint64_t poll_time = check_time - self->prepare_time_ ;
532+ uint64_t latency = self->prepare_time_ - self->check_time_ ;
533+
534+ if (self->timeout_ >= 0 ) {
535+ uint64_t timeout_ns = static_cast <uint64_t >(self->timeout_ ) * 1000 * 1000 ;
536+ if (poll_time > timeout_ns) {
537+ latency += poll_time - timeout_ns;
538+ }
539+ }
540+
541+ self->histogram ()->Record (latency == 0 ? 1 : latency);
542+ self->check_time_ = check_time;
543+ }
544+
545+ void ELDHistogram::MemoryInfo (MemoryTracker* tracker) const {
546+ tracker->TrackField (" histogram" , histogram ());
547+ }
548+
549+ void ELDHistogram::OnStart (StartFlags flags) {
550+ if (enabled_ || IsHandleClosing ()) return ;
551+ enabled_ = true ;
552+ if (flags == StartFlags::RESET)
553+ histogram ()->Reset ();
554+ check_time_ = uv_hrtime ();
555+ prepare_time_ = check_time_;
556+ timeout_ = 0 ;
557+ uv_check_start (&check_handle_, CheckCB);
558+ uv_prepare_start (&prepare_handle_, PrepareCB);
559+ uv_unref (reinterpret_cast <uv_handle_t *>(&check_handle_));
560+ uv_unref (reinterpret_cast <uv_handle_t *>(&prepare_handle_));
561+ }
562+
563+ void ELDHistogram::OnStop () {
564+ if (!enabled_ || IsHandleClosing ()) return ;
565+ enabled_ = false ;
566+ uv_check_stop (&check_handle_);
567+ uv_prepare_stop (&prepare_handle_);
568+ }
569+
570+ void ELDHistogram::PrepareCloseCB (uv_handle_t * handle) {
571+ ELDHistogram* self = static_cast <ELDHistogram*>(handle->data );
572+ uv_close (reinterpret_cast <uv_handle_t *>(&self->check_handle_ ),
573+ HandleWrap::OnClose);
574+ }
575+
576+ void ELDHistogram::Close (Local<Value> close_callback) {
577+ if (IsHandleClosing ()) return ;
578+ OnStop ();
579+ state_ = kClosing ;
580+
581+ if (!close_callback.IsEmpty () && close_callback->IsFunction () &&
582+ !persistent ().IsEmpty ()) {
583+ object ()->Set (env ()->context (),
584+ env ()->handle_onclose_symbol (),
585+ close_callback).Check ();
586+ }
587+
588+ uv_close (reinterpret_cast <uv_handle_t *>(&prepare_handle_),
589+ PrepareCloseCB);
590+ }
591+
592+ void ELDHistogram::Start (const FunctionCallbackInfo<Value>& args) {
593+ ELDHistogram* histogram;
594+ ASSIGN_OR_RETURN_UNWRAP (&histogram, args.This ());
595+ histogram->OnStart (args[0 ]->IsTrue () ? StartFlags::RESET : StartFlags::NONE);
596+ }
597+
598+ void ELDHistogram::FastStart (Local<Value> receiver, bool reset) {
599+ TRACK_V8_FAST_API_CALL (" histogram.start" );
600+ ELDHistogram* histogram;
601+ ASSIGN_OR_RETURN_UNWRAP (&histogram, receiver);
602+ histogram->OnStart (reset ? StartFlags::RESET : StartFlags::NONE);
603+ }
604+
605+ void ELDHistogram::Stop (const FunctionCallbackInfo<Value>& args) {
606+ ELDHistogram* histogram;
607+ ASSIGN_OR_RETURN_UNWRAP (&histogram, args.This ());
608+ histogram->OnStop ();
609+ }
610+
611+ void ELDHistogram::FastStop (Local<Value> receiver) {
612+ TRACK_V8_FAST_API_CALL (" histogram.stop" );
613+ ELDHistogram* histogram;
614+ ASSIGN_OR_RETURN_UNWRAP (&histogram, receiver);
615+ histogram->OnStop ();
616+ }
617+
447618void HistogramImpl::GetCount (const FunctionCallbackInfo<Value>& args) {
448619 HistogramImpl* histogram = HistogramImpl::FromJSObject (args.This ());
449620 double value = static_cast <double >((*histogram)->Count ());
@@ -607,6 +778,11 @@ HistogramImpl* HistogramImpl::FromJSObject(Local<Value> value) {
607778 HistogramImpl::kImplField , EmbedderDataTag::kDefault ));
608779}
609780
781+ std::unique_ptr<worker::TransferData>
782+ ELDHistogram::CloneForMessaging () const {
783+ return std::make_unique<HistogramBase::HistogramTransferData>(histogram ());
784+ }
785+
610786std::unique_ptr<worker::TransferData>
611787IntervalHistogram::CloneForMessaging () const {
612788 return std::make_unique<HistogramBase::HistogramTransferData>(histogram ());
0 commit comments