worker: add cpuUsage for worker · nodejs/node@bd68fbd
@@ -32,6 +32,7 @@ using v8::Isolate;
3232using v8::Local;
3333using v8::Locker;
3434using v8::Maybe;
35+using v8::Name;
3536using v8::Null;
3637using v8::Number;
3738using v8::Object;
@@ -810,6 +811,81 @@ void Worker::Unref(const FunctionCallbackInfo<Value>& args) {
810811 }
811812}
812813814+class WorkerCpuUsageTaker : public AsyncWrap {
815+public:
816+WorkerCpuUsageTaker(Environment* env, Local<Object> obj)
817+ : AsyncWrap(env, obj, AsyncWrap::PROVIDER_WORKERCPUUSAGE) {}
818+819+SET_NO_MEMORY_INFO()
820+SET_MEMORY_INFO_NAME(WorkerCpuUsageTaker)
821+SET_SELF_SIZE(WorkerCpuUsageTaker)
822+};
823+824+void Worker::CpuUsage(const FunctionCallbackInfo<Value>& args) {
825+ Worker* w;
826+ASSIGN_OR_RETURN_UNWRAP(&w, args.This());
827+828+ Environment* env = w->env();
829+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope(w);
830+ Local<Object> wrap;
831+if (!env->worker_cpu_usage_taker_template()
832+ ->NewInstance(env->context())
833+ .ToLocal(&wrap)) {
834+return;
835+ }
836+837+ BaseObjectPtr<WorkerCpuUsageTaker> taker =
838+ MakeDetachedBaseObject<WorkerCpuUsageTaker>(env, wrap);
839+840+bool scheduled = w->RequestInterrupt([taker = std::move(taker),
841+ env](Environment* worker_env) mutable {
842+auto cpu_usage_stats = std::make_unique<uv_rusage_t>();
843+int err = uv_getrusage_thread(cpu_usage_stats.get());
844+845+ env->SetImmediateThreadsafe(
846+ [taker = std::move(taker),
847+ cpu_usage_stats = std::move(cpu_usage_stats),
848+ err = err](Environment* env) mutable {
849+ Isolate* isolate = env->isolate();
850+ HandleScope handle_scope(isolate);
851+ Context::Scope context_scope(env->context());
852+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope(taker.get());
853+854+ Local<Value> argv[] = {
855+Null(isolate),
856+Undefined(isolate),
857+ };
858+859+if (err) {
860+ argv[0] = UVException(
861+ isolate, err, "uv_getrusage_thread", nullptr, nullptr, nullptr);
862+ } else {
863+ Local<Name> names[] = {
864+FIXED_ONE_BYTE_STRING(isolate, "user"),
865+FIXED_ONE_BYTE_STRING(isolate, "system"),
866+ };
867+ Local<Value> values[] = {
868+Number::New(isolate,
869+1e6 * cpu_usage_stats->ru_utime.tv_sec +
870+ cpu_usage_stats->ru_utime.tv_usec),
871+Number::New(isolate,
872+1e6 * cpu_usage_stats->ru_stime.tv_sec +
873+ cpu_usage_stats->ru_stime.tv_usec),
874+ };
875+ argv[1] = Object::New(
876+ isolate, Null(isolate), names, values, arraysize(names));
877+ }
878+879+ taker->MakeCallback(env->ondone_string(), arraysize(argv), argv);
880+ },
881+ CallbackFlags::kUnrefed);
882+ });
883+884+if (scheduled) {
885+ args.GetReturnValue().Set(wrap);
886+ }
887+}
888+813889class WorkerHeapStatisticsTaker : public AsyncWrap {
814890public:
815891WorkerHeapStatisticsTaker(Environment* env, Local<Object> obj)
@@ -1101,6 +1177,7 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11011177SetProtoMethod(isolate, w, "loopIdleTime", Worker::LoopIdleTime);
11021178SetProtoMethod(isolate, w, "loopStartTime", Worker::LoopStartTime);
11031179SetProtoMethod(isolate, w, "getHeapStatistics", Worker::GetHeapStatistics);
1180+SetProtoMethod(isolate, w, "cpuUsage", Worker::CpuUsage);
1104118111051182SetConstructorFunction(isolate, target, "Worker", w);
11061183 }
@@ -1133,6 +1210,19 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11331210 wst->InstanceTemplate());
11341211 }
113512121213+ {
1214+ Local<FunctionTemplate> wst = NewFunctionTemplate(isolate, nullptr);
1215+1216+ wst->InstanceTemplate()->SetInternalFieldCount(
1217+ WorkerCpuUsageTaker::kInternalFieldCount);
1218+ wst->Inherit(AsyncWrap::GetConstructorTemplate(isolate_data));
1219+1220+ Local<String> wst_string =
1221+FIXED_ONE_BYTE_STRING(isolate, "WorkerCpuUsageTaker");
1222+ wst->SetClassName(wst_string);
1223+ isolate_data->set_worker_cpu_usage_taker_template(wst->InstanceTemplate());
1224+ }
1225+11361226SetMethod(isolate, target, "getEnvMessagePort", GetEnvMessagePort);
11371227}
11381228@@ -1199,6 +1289,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
11991289 registry->Register(Worker::LoopIdleTime);
12001290 registry->Register(Worker::LoopStartTime);
12011291 registry->Register(Worker::GetHeapStatistics);
1292+ registry->Register(Worker::CpuUsage);
12021293}
1203129412041295} // anonymous namespace