@@ -810,6 +810,85 @@ void Worker::Unref(const FunctionCallbackInfo<Value>& args) {
810810 }
811811}
812812
813+ class WorkerCpuUsageTaker : public AsyncWrap {
814+ public:
815+ WorkerCpuUsageTaker (Environment* env, Local<Object> obj)
816+ : AsyncWrap(env, obj, AsyncWrap::PROVIDER_WORKERCPUUSAGE) {}
817+
818+ SET_NO_MEMORY_INFO ()
819+ SET_MEMORY_INFO_NAME (WorkerCpuUsageTaker)
820+ SET_SELF_SIZE (WorkerCpuUsageTaker)
821+ };
822+
823+ void Worker::CpuUsage (const FunctionCallbackInfo<Value>& args) {
824+ Worker* w;
825+ ASSIGN_OR_RETURN_UNWRAP (&w, args.This ());
826+
827+ Environment* env = w->env ();
828+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope (w);
829+ Local<Object> wrap;
830+ if (!env->worker_cpu_usage_taker_template ()
831+ ->NewInstance (env->context ())
832+ .ToLocal (&wrap)) {
833+ return ;
834+ }
835+
836+ std::unique_ptr<BaseObjectPtr<WorkerCpuUsageTaker>> taker =
837+ std::make_unique<BaseObjectPtr<WorkerCpuUsageTaker>>(
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<v8::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->get ()->MakeCallback (
880+ env->ondone_string (), arraysize (argv), argv);
881+ },
882+ CallbackFlags::kUnrefed );
883+ });
884+
885+ if (scheduled) {
886+ args.GetReturnValue ().Set (wrap);
887+ } else {
888+ args.GetReturnValue ().Set (Local<Object>());
889+ }
890+ }
891+
813892class WorkerHeapStatisticsTaker : public AsyncWrap {
814893 public:
815894 WorkerHeapStatisticsTaker (Environment* env, Local<Object> obj)
@@ -1101,6 +1180,7 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11011180 SetProtoMethod (isolate, w, " loopIdleTime" , Worker::LoopIdleTime);
11021181 SetProtoMethod (isolate, w, " loopStartTime" , Worker::LoopStartTime);
11031182 SetProtoMethod (isolate, w, " getHeapStatistics" , Worker::GetHeapStatistics);
1183+ SetProtoMethod (isolate, w, " cpuUsage" , Worker::CpuUsage);
11041184
11051185 SetConstructorFunction (isolate, target, " Worker" , w);
11061186 }
@@ -1133,6 +1213,19 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11331213 wst->InstanceTemplate ());
11341214 }
11351215
1216+ {
1217+ Local<FunctionTemplate> wst = NewFunctionTemplate (isolate, nullptr );
1218+
1219+ wst->InstanceTemplate ()->SetInternalFieldCount (
1220+ WorkerCpuUsageTaker::kInternalFieldCount );
1221+ wst->Inherit (AsyncWrap::GetConstructorTemplate (isolate_data));
1222+
1223+ Local<String> wst_string =
1224+ FIXED_ONE_BYTE_STRING (isolate, " WorkerCpuUsageTaker" );
1225+ wst->SetClassName (wst_string);
1226+ isolate_data->set_worker_cpu_usage_taker_template (wst->InstanceTemplate ());
1227+ }
1228+
11361229 SetMethod (isolate, target, " getEnvMessagePort" , GetEnvMessagePort);
11371230}
11381231
@@ -1199,6 +1292,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
11991292 registry->Register (Worker::LoopIdleTime);
12001293 registry->Register (Worker::LoopStartTime);
12011294 registry->Register (Worker::GetHeapStatistics);
1295+ registry->Register (Worker::CpuUsage);
12021296}
12031297
12041298} // anonymous namespace
0 commit comments