@@ -25,6 +25,20 @@ using v8::String;
2525using v8::Uint32;
2626using v8::Value;
2727
28+ template <typename T>
29+ void StartHandleHistogram (Local<Value> receiver, bool reset) {
30+ T* histogram;
31+ ASSIGN_OR_RETURN_UNWRAP (&histogram, receiver);
32+ histogram->OnStart (reset ? T::StartFlags::RESET : T::StartFlags::NONE );
33+ }
34+
35+ template <typename T>
36+ void StopHandleHistogram (Local<Value> receiver) {
37+ T* histogram;
38+ ASSIGN_OR_RETURN_UNWRAP (&histogram, receiver);
39+ histogram->OnStop ();
40+ }
41+
2842Histogram::Histogram (const Options& options) {
2943 hdr_histogram* histogram;
3044 CHECK_EQ (0 , hdr_init (options.lowest ,
@@ -68,6 +82,10 @@ CFunction IntervalHistogram::fast_start_(
6882 CFunction::Make (&IntervalHistogram::FastStart));
6983CFunction IntervalHistogram::fast_stop_ (
7084 CFunction::Make (&IntervalHistogram::FastStop));
85+ CFunction IterationHistogram::fast_start_ (
86+ CFunction::Make (&IterationHistogram::FastStart));
87+ CFunction IterationHistogram::fast_stop_ (
88+ CFunction::Make (&IterationHistogram::FastStop));
7189
7290void HistogramImpl::AddMethods (Isolate* isolate, Local<FunctionTemplate> tmpl) {
7391 // TODO(@jasnell): The bigint API variations do not yet support fast
@@ -416,29 +434,156 @@ void IntervalHistogram::OnStop() {
416434}
417435
418436void IntervalHistogram::Start (const FunctionCallbackInfo<Value>& args) {
419- IntervalHistogram* histogram;
420- ASSIGN_OR_RETURN_UNWRAP (&histogram, args.This ());
421- histogram->OnStart (args[0 ]->IsTrue () ? StartFlags::RESET : StartFlags::NONE );
437+ StartHandleHistogram<IntervalHistogram>(args.This (), args[0 ]->IsTrue ());
422438}
423439
424440void IntervalHistogram::FastStart (Local<Value> receiver, bool reset) {
425441 TRACK_V8_FAST_API_CALL (" histogram.start" );
426- IntervalHistogram* histogram;
427- ASSIGN_OR_RETURN_UNWRAP (&histogram, receiver);
428- histogram->OnStart (reset ? StartFlags::RESET : StartFlags::NONE );
442+ StartHandleHistogram<IntervalHistogram>(receiver, reset);
429443}
430444
431445void IntervalHistogram::Stop (const FunctionCallbackInfo<Value>& args) {
432- IntervalHistogram* histogram;
433- ASSIGN_OR_RETURN_UNWRAP (&histogram, args.This ());
434- histogram->OnStop ();
446+ StopHandleHistogram<IntervalHistogram>(args.This ());
435447}
436448
437449void IntervalHistogram::FastStop (Local<Value> receiver) {
438450 TRACK_V8_FAST_API_CALL (" histogram.stop" );
439- IntervalHistogram* histogram;
440- ASSIGN_OR_RETURN_UNWRAP (&histogram, receiver);
441- histogram->OnStop ();
451+ StopHandleHistogram<IntervalHistogram>(receiver);
452+ }
453+
454+ Local<FunctionTemplate> IterationHistogram::GetConstructorTemplate (
455+ Environment* env) {
456+ Local<FunctionTemplate> tmpl = env->iterationhistogram_constructor_template ();
457+ if (tmpl.IsEmpty ()) {
458+ Isolate* isolate = env->isolate ();
459+ tmpl = NewFunctionTemplate (isolate, nullptr );
460+ tmpl->Inherit (HandleWrap::GetConstructorTemplate (env));
461+ tmpl->SetClassName (FIXED_ONE_BYTE_STRING (isolate, " Histogram" ));
462+ auto instance = tmpl->InstanceTemplate ();
463+ instance->SetInternalFieldCount (IterationHistogram::kInternalFieldCount );
464+ HistogramImpl::AddMethods (isolate, tmpl);
465+ SetFastMethod (isolate, instance, " start" , Start, &fast_start_);
466+ SetFastMethod (isolate, instance, " stop" , Stop, &fast_stop_);
467+ env->set_iterationhistogram_constructor_template (tmpl);
468+ }
469+ return tmpl;
470+ }
471+
472+ void IterationHistogram::RegisterExternalReferences (
473+ ExternalReferenceRegistry* registry) {
474+ registry->Register (Start);
475+ registry->Register (Stop);
476+ registry->Register (fast_start_);
477+ registry->Register (fast_stop_);
478+ HistogramImpl::RegisterExternalReferences (registry);
479+ }
480+
481+ IterationHistogram::IterationHistogram (Environment* env,
482+ Local<Object> wrap,
483+ AsyncWrap::ProviderType type,
484+ const Histogram::Options& options)
485+ : HandleWrap(
486+ env, wrap, reinterpret_cast <uv_handle_t *>(&check_handle_), type),
487+ HistogramImpl(options) {
488+ MakeWeak ();
489+ wrap->SetAlignedPointerInInternalField (
490+ HistogramImpl::InternalFields::kImplField ,
491+ static_cast <HistogramImpl*>(this ));
492+ uv_check_init (env->event_loop (), &check_handle_);
493+ uv_prepare_init (env->event_loop (), &prepare_handle_);
494+ uv_unref (reinterpret_cast <uv_handle_t *>(&check_handle_));
495+ uv_unref (reinterpret_cast <uv_handle_t *>(&prepare_handle_));
496+ prepare_handle_.data = this ;
497+ }
498+
499+ BaseObjectPtr<IterationHistogram> IterationHistogram::Create (
500+ Environment* env, const Histogram::Options& options) {
501+ Local<Object> obj;
502+ if (!GetConstructorTemplate (env)
503+ ->InstanceTemplate ()
504+ ->NewInstance (env->context ())
505+ .ToLocal (&obj)) {
506+ return nullptr ;
507+ }
508+
509+ return MakeBaseObject<IterationHistogram>(
510+ env, obj, AsyncWrap::PROVIDER_ELDHISTOGRAM , options);
511+ }
512+
513+ void IterationHistogram::PrepareCB (uv_prepare_t * handle) {
514+ IterationHistogram* self = static_cast <IterationHistogram*>(handle->data );
515+ if (!self->enabled_ ) return ;
516+ self->prepare_time_ = uv_hrtime ();
517+ self->timeout_ = uv_backend_timeout (handle->loop );
518+ }
519+
520+ void IterationHistogram::CheckCB (uv_check_t * handle) {
521+ IterationHistogram* self =
522+ ContainerOf (&IterationHistogram::check_handle_, handle);
523+ if (!self->enabled_ ) return ;
524+
525+ uint64_t check_time = uv_hrtime ();
526+ uint64_t poll_time = check_time - self->prepare_time_ ;
527+ uint64_t latency = self->prepare_time_ - self->check_time_ ;
528+
529+ if (self->timeout_ >= 0 ) {
530+ uint64_t timeout_ns = static_cast <uint64_t >(self->timeout_ ) * 1000 * 1000 ;
531+ if (poll_time > timeout_ns) {
532+ latency += poll_time - timeout_ns;
533+ }
534+ }
535+
536+ self->histogram ()->Record (latency == 0 ? 1 : latency);
537+ self->check_time_ = check_time;
538+ }
539+
540+ void IterationHistogram::MemoryInfo (MemoryTracker* tracker) const {
541+ tracker->TrackField (" histogram" , histogram ());
542+ }
543+
544+ void IterationHistogram::OnStart (StartFlags flags) {
545+ if (enabled_ || IsHandleClosing ()) return ;
546+ enabled_ = true ;
547+ if (flags == StartFlags::RESET ) histogram ()->Reset ();
548+ check_time_ = uv_hrtime ();
549+ prepare_time_ = check_time_;
550+ timeout_ = 0 ;
551+ uv_check_start (&check_handle_, CheckCB);
552+ uv_prepare_start (&prepare_handle_, PrepareCB);
553+ uv_unref (reinterpret_cast <uv_handle_t *>(&check_handle_));
554+ uv_unref (reinterpret_cast <uv_handle_t *>(&prepare_handle_));
555+ }
556+
557+ void IterationHistogram::OnStop () {
558+ if (!enabled_ || IsHandleClosing ()) return ;
559+ enabled_ = false ;
560+ uv_check_stop (&check_handle_);
561+ uv_prepare_stop (&prepare_handle_);
562+ }
563+
564+ void IterationHistogram::Close (Local<Value> close_callback) {
565+ if (IsHandleClosing ()) return ;
566+ OnStop ();
567+ HandleWrap::Close (close_callback);
568+ uv_close (reinterpret_cast <uv_handle_t *>(&prepare_handle_), nullptr );
569+ }
570+
571+ void IterationHistogram::Start (const FunctionCallbackInfo<Value>& args) {
572+ StartHandleHistogram<IterationHistogram>(args.This (), args[0 ]->IsTrue ());
573+ }
574+
575+ void IterationHistogram::FastStart (Local<Value> receiver, bool reset) {
576+ TRACK_V8_FAST_API_CALL (" histogram.eventLoopDelay.start" );
577+ StartHandleHistogram<IterationHistogram>(receiver, reset);
578+ }
579+
580+ void IterationHistogram::Stop (const FunctionCallbackInfo<Value>& args) {
581+ StopHandleHistogram<IterationHistogram>(args.This ());
582+ }
583+
584+ void IterationHistogram::FastStop (Local<Value> receiver) {
585+ TRACK_V8_FAST_API_CALL (" histogram.eventLoopDelay.stop" );
586+ StopHandleHistogram<IterationHistogram>(receiver);
442587}
443588
444589void HistogramImpl::GetCount (const FunctionCallbackInfo<Value>& args) {
@@ -604,6 +749,11 @@ HistogramImpl* HistogramImpl::FromJSObject(Local<Value> value) {
604749 obj->GetAlignedPointerFromInternalField (HistogramImpl::kImplField ));
605750}
606751
752+ std::unique_ptr<worker::TransferData> IterationHistogram::CloneForMessaging ()
753+ const {
754+ return std::make_unique<HistogramBase::HistogramTransferData>(histogram ());
755+ }
756+
607757std::unique_ptr<worker::TransferData>
608758IntervalHistogram::CloneForMessaging () const {
609759 return std::make_unique<HistogramBase::HistogramTransferData>(histogram ());
0 commit comments