@@ -350,29 +350,27 @@ IntervalHistogram::IntervalHistogram(
350350 Environment* env,
351351 Local<Object> wrap,
352352 AsyncWrap::ProviderType type,
353- int32_t interval,
354- std::function<void (Histogram&)> on_interval,
355353 const Histogram::Options& options)
356354 : HandleWrap(
357355 env,
358356 wrap,
359- reinterpret_cast <uv_handle_t *>(&timer_ ),
357+ reinterpret_cast <uv_handle_t *>(&check_handle_ ),
360358 type),
361- HistogramImpl(options),
362- interval_(interval),
363- on_interval_(std::move(on_interval)) {
359+ HistogramImpl(options) {
364360 MakeWeak ();
365361 wrap->SetAlignedPointerInInternalField (
366362 HistogramImpl::InternalFields::kImplField ,
367363 static_cast <HistogramImpl*>(this ),
368364 EmbedderDataTag::kDefault );
369- uv_timer_init (env->event_loop (), &timer_);
365+ uv_check_init (env->event_loop (), &check_handle_);
366+ uv_prepare_init (env->event_loop (), &prepare_handle_);
367+ uv_unref (reinterpret_cast <uv_handle_t *>(&check_handle_));
368+ uv_unref (reinterpret_cast <uv_handle_t *>(&prepare_handle_));
369+ prepare_handle_.data = this ;
370370}
371371
372372BaseObjectPtr<IntervalHistogram> IntervalHistogram::Create (
373373 Environment* env,
374- int32_t interval,
375- std::function<void (Histogram&)> on_interval,
376374 const Histogram::Options& options) {
377375 Local<Object> obj;
378376 if (!GetConstructorTemplate (env)
@@ -385,18 +383,34 @@ BaseObjectPtr<IntervalHistogram> IntervalHistogram::Create(
385383 env,
386384 obj,
387385 AsyncWrap::PROVIDER_ELDHISTOGRAM,
388- interval,
389- std::move (on_interval),
390386 options);
391387}
392388
393- void IntervalHistogram::TimerCB (uv_timer_t * handle) {
394- IntervalHistogram* histogram =
395- ContainerOf (&IntervalHistogram::timer_, handle);
389+ void IntervalHistogram::PrepareCB (uv_prepare_t * handle) {
390+ IntervalHistogram* self = static_cast <IntervalHistogram*>(handle->data );
391+ if (!self->enabled_ ) return ;
392+ self->prepare_time_ = uv_hrtime ();
393+ self->timeout_ = uv_backend_timeout (handle->loop );
394+ }
395+
396+ void IntervalHistogram::CheckCB (uv_check_t * handle) {
397+ IntervalHistogram* self =
398+ ContainerOf (&IntervalHistogram::check_handle_, handle);
399+ if (!self->enabled_ ) return ;
396400
397- Histogram* h = histogram->histogram ().get ();
401+ uint64_t check_time = uv_hrtime ();
402+ uint64_t poll_time = check_time - self->prepare_time_ ;
403+ uint64_t latency = self->prepare_time_ - self->check_time_ ;
398404
399- histogram->on_interval_ (*h);
405+ if (self->timeout_ >= 0 ) {
406+ uint64_t timeout_ns = static_cast <uint64_t >(self->timeout_ ) * 1000 * 1000 ;
407+ if (poll_time > timeout_ns) {
408+ latency += poll_time - timeout_ns;
409+ }
410+ }
411+
412+ self->histogram ()->Record (latency == 0 ? 1 : latency);
413+ self->check_time_ = check_time;
400414}
401415
402416void IntervalHistogram::MemoryInfo (MemoryTracker* tracker) const {
@@ -408,14 +422,42 @@ void IntervalHistogram::OnStart(StartFlags flags) {
408422 enabled_ = true ;
409423 if (flags == StartFlags::RESET)
410424 histogram ()->Reset ();
411- uv_timer_start (&timer_, TimerCB, interval_, interval_);
412- uv_unref (reinterpret_cast <uv_handle_t *>(&timer_));
425+ check_time_ = uv_hrtime ();
426+ prepare_time_ = check_time_;
427+ timeout_ = 0 ;
428+ uv_check_start (&check_handle_, CheckCB);
429+ uv_prepare_start (&prepare_handle_, PrepareCB);
430+ uv_unref (reinterpret_cast <uv_handle_t *>(&check_handle_));
431+ uv_unref (reinterpret_cast <uv_handle_t *>(&prepare_handle_));
413432}
414433
415434void IntervalHistogram::OnStop () {
416435 if (!enabled_ || IsHandleClosing ()) return ;
417436 enabled_ = false ;
418- uv_timer_stop (&timer_);
437+ uv_check_stop (&check_handle_);
438+ uv_prepare_stop (&prepare_handle_);
439+ }
440+
441+ void IntervalHistogram::PrepareCloseCB (uv_handle_t * handle) {
442+ IntervalHistogram* self = static_cast <IntervalHistogram*>(handle->data );
443+ uv_close (reinterpret_cast <uv_handle_t *>(&self->check_handle_ ),
444+ HandleWrap::OnClose);
445+ }
446+
447+ void IntervalHistogram::Close (Local<Value> close_callback) {
448+ if (IsHandleClosing ()) return ;
449+ OnStop ();
450+ state_ = kClosing ;
451+
452+ if (!close_callback.IsEmpty () && close_callback->IsFunction () &&
453+ !persistent ().IsEmpty ()) {
454+ object ()->Set (env ()->context (),
455+ env ()->handle_onclose_symbol (),
456+ close_callback).Check ();
457+ }
458+
459+ uv_close (reinterpret_cast <uv_handle_t *>(&prepare_handle_),
460+ PrepareCloseCB);
419461}
420462
421463void IntervalHistogram::Start (const FunctionCallbackInfo<Value>& args) {
0 commit comments