@@ -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,84 @@ void Worker::Unref(const FunctionCallbackInfo<Value>& args) {
810811 }
811812}
812813
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+ 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 (
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