Skip to content

Commit 3dab395

Browse files
committed
src: add a native mode to monitorEventLoopDelay
1 parent a5b3d76 commit 3dab395

6 files changed

Lines changed: 194 additions & 3 deletions

File tree

lib/internal/perf/event_loop_delay.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const {
1818
} = internalBinding('performance');
1919

2020
const {
21+
validateBoolean,
2122
validateInteger,
2223
validateObject,
2324
} = require('internal/validators');
@@ -74,21 +75,23 @@ class ELDHistogram extends Histogram {
7475

7576
/**
7677
* @param {{
77-
* resolution : number
78+
* resolution? : number,
79+
* native? : boolean
7880
* }} [options]
7981
* @returns {ELDHistogram}
8082
*/
8183
function monitorEventLoopDelay(options = kEmptyObject) {
8284
validateObject(options, 'options');
8385

84-
const { resolution = 10 } = options;
86+
const { resolution = 10, native = false } = options;
8587
validateInteger(resolution, 'options.resolution', 1);
88+
validateBoolean(native, 'options.native');
8689

8790
return ReflectConstruct(
8891
function() {
8992
markTransferMode(this, true, false);
9093
this[kEnabled] = false;
91-
this[kHandle] = createELDHistogram(resolution);
94+
this[kHandle] = createELDHistogram(resolution, native);
9295
this[kMap] = new SafeMap();
9396
}, [], ELDHistogram);
9497
}

src/async_wrap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace node {
3636
V(DIRHANDLE) \
3737
V(DNSCHANNEL) \
3838
V(ELDHISTOGRAM) \
39+
V(ELDNATIVEHISTOGRAM) \
3940
V(FILEHANDLE) \
4041
V(FILEHANDLECLOSEREQ) \
4142
V(BLOBREADER) \

src/env_properties.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@
424424
V(http2stream_constructor_template, v8::ObjectTemplate) \
425425
V(http2ping_constructor_template, v8::ObjectTemplate) \
426426
V(i18n_converter_template, v8::ObjectTemplate) \
427+
V(eld_native_histogram_constructor_template, v8::FunctionTemplate) \
427428
V(intervalhistogram_constructor_template, v8::FunctionTemplate) \
428429
V(iter_template, v8::DictionaryTemplate) \
429430
V(js_transferable_constructor_template, v8::FunctionTemplate) \

src/histogram.cc

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,4 +612,135 @@ IntervalHistogram::CloneForMessaging() const {
612612
return std::make_unique<HistogramBase::HistogramTransferData>(histogram());
613613
}
614614

615+
CFunction ELDNativeHistogram::fast_start_(
616+
CFunction::Make(&ELDNativeHistogram::FastStart));
617+
CFunction ELDNativeHistogram::fast_stop_(
618+
CFunction::Make(&ELDNativeHistogram::FastStop));
619+
620+
Local<FunctionTemplate> ELDNativeHistogram::GetConstructorTemplate(
621+
Environment* env) {
622+
Local<FunctionTemplate> tmpl =
623+
env->eld_native_histogram_constructor_template();
624+
if (tmpl.IsEmpty()) {
625+
Isolate* isolate = env->isolate();
626+
tmpl = NewFunctionTemplate(isolate, nullptr);
627+
tmpl->Inherit(HandleWrap::GetConstructorTemplate(env));
628+
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "Histogram"));
629+
auto instance = tmpl->InstanceTemplate();
630+
instance->SetInternalFieldCount(ELDNativeHistogram::kInternalFieldCount);
631+
HistogramImpl::AddMethods(isolate, tmpl);
632+
SetFastMethod(isolate, instance, "start", Start, &fast_start_);
633+
SetFastMethod(isolate, instance, "stop", Stop, &fast_stop_);
634+
env->set_eld_native_histogram_constructor_template(tmpl);
635+
}
636+
return tmpl;
637+
}
638+
639+
void ELDNativeHistogram::RegisterExternalReferences(
640+
ExternalReferenceRegistry* registry) {
641+
registry->Register(Start);
642+
registry->Register(Stop);
643+
registry->Register(fast_start_);
644+
registry->Register(fast_stop_);
645+
HistogramImpl::RegisterExternalReferences(registry);
646+
}
647+
648+
ELDNativeHistogram::ELDNativeHistogram(Environment* env, Local<Object> wrap)
649+
: HandleWrap(
650+
env,
651+
wrap,
652+
reinterpret_cast<uv_handle_t*>(&check_),
653+
AsyncWrap::PROVIDER_ELDNATIVEHISTOGRAM),
654+
HistogramImpl() {
655+
MakeWeak();
656+
wrap->SetAlignedPointerInInternalField(
657+
HistogramImpl::InternalFields::kImplField,
658+
static_cast<HistogramImpl*>(this),
659+
EmbedderDataTag::kDefault);
660+
uv_check_init(env->event_loop(), &check_);
661+
}
662+
663+
BaseObjectPtr<ELDNativeHistogram> ELDNativeHistogram::Create(
664+
Environment* env) {
665+
Local<Object> obj;
666+
if (!GetConstructorTemplate(env)
667+
->InstanceTemplate()
668+
->NewInstance(env->context())
669+
.ToLocal(&obj)) {
670+
return nullptr;
671+
}
672+
return MakeBaseObject<ELDNativeHistogram>(env, obj);
673+
}
674+
675+
void ELDNativeHistogram::CheckCB(uv_check_t* handle) {
676+
ELDNativeHistogram* histogram =
677+
ContainerOf(&ELDNativeHistogram::check_, handle);
678+
679+
uint64_t now = uv_hrtime();
680+
uint64_t idle_now = uv_metrics_idle_time(histogram->env()->event_loop());
681+
682+
if (histogram->prev_hrtime_ > 0) {
683+
uint64_t total = now - histogram->prev_hrtime_;
684+
uint64_t idle = idle_now - histogram->prev_idle_time_;
685+
if (idle > total) idle = total;
686+
int64_t busy = static_cast<int64_t>(total - idle);
687+
if (busy > 0)
688+
histogram->histogram()->Record(busy);
689+
}
690+
691+
histogram->prev_hrtime_ = now;
692+
histogram->prev_idle_time_ = idle_now;
693+
}
694+
695+
void ELDNativeHistogram::MemoryInfo(MemoryTracker* tracker) const {
696+
tracker->TrackField("histogram", histogram());
697+
}
698+
699+
void ELDNativeHistogram::OnStart(bool reset) {
700+
if (enabled_ || IsHandleClosing()) return;
701+
enabled_ = true;
702+
if (reset) histogram()->Reset();
703+
prev_hrtime_ = 0;
704+
prev_idle_time_ = 0;
705+
uv_check_start(&check_, CheckCB);
706+
uv_unref(reinterpret_cast<uv_handle_t*>(&check_));
707+
}
708+
709+
void ELDNativeHistogram::OnStop() {
710+
if (!enabled_ || IsHandleClosing()) return;
711+
enabled_ = false;
712+
uv_check_stop(&check_);
713+
}
714+
715+
void ELDNativeHistogram::Start(const FunctionCallbackInfo<Value>& args) {
716+
ELDNativeHistogram* histogram;
717+
ASSIGN_OR_RETURN_UNWRAP(&histogram, args.This());
718+
histogram->OnStart(args[0]->IsTrue());
719+
}
720+
721+
void ELDNativeHistogram::FastStart(Local<Value> receiver, bool reset) {
722+
TRACK_V8_FAST_API_CALL("histogram.start");
723+
ELDNativeHistogram* histogram;
724+
ASSIGN_OR_RETURN_UNWRAP(&histogram, receiver);
725+
histogram->OnStart(reset);
726+
}
727+
728+
void ELDNativeHistogram::Stop(const FunctionCallbackInfo<Value>& args) {
729+
ELDNativeHistogram* histogram;
730+
ASSIGN_OR_RETURN_UNWRAP(&histogram, args.This());
731+
histogram->OnStop();
732+
}
733+
734+
void ELDNativeHistogram::FastStop(Local<Value> receiver) {
735+
TRACK_V8_FAST_API_CALL("histogram.stop");
736+
ELDNativeHistogram* histogram;
737+
ASSIGN_OR_RETURN_UNWRAP(&histogram, receiver);
738+
histogram->OnStop();
739+
}
740+
741+
std::unique_ptr<worker::TransferData>
742+
ELDNativeHistogram::CloneForMessaging() const {
743+
return std::make_unique<HistogramBase::HistogramTransferData>(histogram());
744+
}
745+
615746
} // namespace node

src/histogram.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,51 @@ class IntervalHistogram final : public HandleWrap, public HistogramImpl {
266266
static v8::CFunction fast_stop_;
267267
};
268268

269+
class ELDNativeHistogram final : public HandleWrap, public HistogramImpl {
270+
public:
271+
enum InternalFields {
272+
kInternalFieldCount = std::max<uint32_t>(
273+
HandleWrap::kInternalFieldCount, HistogramImpl::kInternalFieldCount),
274+
};
275+
276+
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
277+
278+
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(
279+
Environment* env);
280+
281+
static BaseObjectPtr<ELDNativeHistogram> Create(Environment* env);
282+
283+
ELDNativeHistogram(Environment* env, v8::Local<v8::Object> wrap);
284+
285+
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
286+
static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);
287+
288+
static void FastStart(v8::Local<v8::Value> receiver, bool reset);
289+
static void FastStop(v8::Local<v8::Value> receiver);
290+
291+
BaseObject::TransferMode GetTransferMode() const override {
292+
return TransferMode::kCloneable;
293+
}
294+
std::unique_ptr<worker::TransferData> CloneForMessaging() const override;
295+
296+
void MemoryInfo(MemoryTracker* tracker) const override;
297+
SET_MEMORY_INFO_NAME(ELDNativeHistogram)
298+
SET_SELF_SIZE(ELDNativeHistogram)
299+
300+
private:
301+
static void CheckCB(uv_check_t* handle);
302+
void OnStart(bool reset);
303+
void OnStop();
304+
305+
bool enabled_ = false;
306+
uint64_t prev_hrtime_ = 0;
307+
uint64_t prev_idle_time_ = 0;
308+
uv_check_t check_;
309+
310+
static v8::CFunction fast_start_;
311+
static v8::CFunction fast_stop_;
312+
};
313+
269314
} // namespace node
270315

271316
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

src/node_perf.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,15 @@ void CreateELDHistogram(const FunctionCallbackInfo<Value>& args) {
282282
Environment* env = Environment::GetCurrent(args);
283283
int64_t interval = args[0].As<Integer>()->Value();
284284
CHECK_GT(interval, 0);
285+
286+
if (args[1]->IsTrue()) {
287+
BaseObjectPtr<ELDNativeHistogram> histogram =
288+
ELDNativeHistogram::Create(env);
289+
if (histogram)
290+
args.GetReturnValue().Set(histogram->object());
291+
return;
292+
}
293+
285294
BaseObjectPtr<IntervalHistogram> histogram =
286295
IntervalHistogram::Create(env, interval, [](Histogram& histogram) {
287296
uint64_t delta = histogram.RecordDelta();
@@ -413,6 +422,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
413422
registry->Register(fast_performance_now);
414423
HistogramBase::RegisterExternalReferences(registry);
415424
IntervalHistogram::RegisterExternalReferences(registry);
425+
ELDNativeHistogram::RegisterExternalReferences(registry);
416426
}
417427
} // namespace performance
418428
} // namespace node

0 commit comments

Comments
 (0)