@@ -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}
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 (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 {
814890 public:
815891 WorkerHeapStatisticsTaker (Environment* env, Local<Object> obj)
@@ -1101,6 +1177,7 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11011177 SetProtoMethod (isolate, w, " loopIdleTime" , Worker::LoopIdleTime);
11021178 SetProtoMethod (isolate, w, " loopStartTime" , Worker::LoopStartTime);
11031179 SetProtoMethod (isolate, w, " getHeapStatistics" , Worker::GetHeapStatistics);
1180+ SetProtoMethod (isolate, w, " cpuUsage" , Worker::CpuUsage);
11041181
11051182 SetConstructorFunction (isolate, target, " Worker" , w);
11061183 }
@@ -1133,6 +1210,19 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11331210 wst->InstanceTemplate ());
11341211 }
11351212
1213+ {
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+
11361226 SetMethod (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}
12031294
12041295} // anonymous namespace
0 commit comments