@@ -810,6 +810,97 @@ void Worker::Unref(const FunctionCallbackInfo<Value>& args) {
810810 }
811811}
812812
813+
814+ 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+ std::unique_ptr<BaseObjectPtr<WorkerCpuUsageTaker>> taker =
838+ std::make_unique<BaseObjectPtr<WorkerCpuUsageTaker>>(
839+ MakeDetachedBaseObject<WorkerCpuUsageTaker>(env, wrap));
840+
841+ bool scheduled = w->RequestInterrupt ([taker = std::move (taker),
842+ env](Environment* worker_env) mutable {
843+ auto cpu_usage_stats = std::make_unique<uv_rusage_t >();
844+ int err = uv_getrusage_thread (cpu_usage_stats.get ());
845+
846+ env->SetImmediateThreadsafe (
847+ [
848+ taker = std::move (taker),
849+ cpu_usage_stats = std::move (cpu_usage_stats),
850+ err = err
851+ ](Environment* env) mutable {
852+ Isolate* isolate = env->isolate ();
853+ HandleScope handle_scope (isolate);
854+ Context::Scope context_scope (env->context ());
855+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope (taker->get ());
856+
857+ Local<Value> argv[] = {
858+ Null (isolate),
859+ Undefined (isolate),
860+ };
861+
862+ if (err) {
863+ argv[0 ] = UVException (isolate,
864+ err,
865+ " uv_getrusage_thread" ,
866+ nullptr ,
867+ nullptr ,
868+ nullptr );
869+ } else {
870+ Local<v8::Name> names[] = {
871+ FIXED_ONE_BYTE_STRING (isolate, " user" ),
872+ FIXED_ONE_BYTE_STRING (isolate, " system" ),
873+ };
874+ Local<Value> values[] = {
875+ Number::New (isolate,
876+ 1e6 *
877+ cpu_usage_stats->ru_utime .tv_sec +
878+ cpu_usage_stats->ru_utime .tv_usec ),
879+ Number::New (isolate,
880+ 1e6 *
881+ cpu_usage_stats->ru_stime .tv_sec +
882+ cpu_usage_stats->ru_stime .tv_usec ),
883+ };
884+ argv[1 ] = Object::New (isolate,
885+ Null (isolate),
886+ names,
887+ values,
888+ arraysize (names));
889+ }
890+
891+ taker->get ()->MakeCallback (
892+ env->ondone_string (), arraysize (argv), argv);
893+ },
894+ CallbackFlags::kUnrefed );
895+ });
896+
897+ if (scheduled) {
898+ args.GetReturnValue ().Set (wrap);
899+ } else {
900+ args.GetReturnValue ().Set (Local<Object>());
901+ }
902+ }
903+
813904class WorkerHeapStatisticsTaker : public AsyncWrap {
814905 public:
815906 WorkerHeapStatisticsTaker (Environment* env, Local<Object> obj)
@@ -1101,6 +1192,7 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11011192 SetProtoMethod (isolate, w, " loopIdleTime" , Worker::LoopIdleTime);
11021193 SetProtoMethod (isolate, w, " loopStartTime" , Worker::LoopStartTime);
11031194 SetProtoMethod (isolate, w, " getHeapStatistics" , Worker::GetHeapStatistics);
1195+ SetProtoMethod (isolate, w, " cpuUsage" , Worker::CpuUsage);
11041196
11051197 SetConstructorFunction (isolate, target, " Worker" , w);
11061198 }
@@ -1133,6 +1225,20 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11331225 wst->InstanceTemplate ());
11341226 }
11351227
1228+ {
1229+ Local<FunctionTemplate> wst = NewFunctionTemplate (isolate, nullptr );
1230+
1231+ wst->InstanceTemplate ()->SetInternalFieldCount (
1232+ WorkerCpuUsageTaker::kInternalFieldCount );
1233+ wst->Inherit (AsyncWrap::GetConstructorTemplate (isolate_data));
1234+
1235+ Local<String> wst_string =
1236+ FIXED_ONE_BYTE_STRING (isolate, " WorkerCpuUsageTaker" );
1237+ wst->SetClassName (wst_string);
1238+ isolate_data->set_worker_cpu_usage_taker_template (
1239+ wst->InstanceTemplate ());
1240+ }
1241+
11361242 SetMethod (isolate, target, " getEnvMessagePort" , GetEnvMessagePort);
11371243}
11381244
@@ -1199,6 +1305,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
11991305 registry->Register (Worker::LoopIdleTime);
12001306 registry->Register (Worker::LoopStartTime);
12011307 registry->Register (Worker::GetHeapStatistics);
1308+ registry->Register (Worker::CpuUsage);
12021309}
12031310
12041311} // anonymous namespace
0 commit comments