@@ -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;
@@ -811,6 +812,81 @@ void Worker::Unref(const FunctionCallbackInfo<Value>& args) {
811812 }
812813}
813814
815+ class WorkerCpuUsageTaker : public AsyncWrap {
816+ public:
817+ WorkerCpuUsageTaker (Environment* env, Local<Object> obj)
818+ : AsyncWrap(env, obj, AsyncWrap::PROVIDER_WORKERCPUUSAGE) {}
819+
820+ SET_NO_MEMORY_INFO ()
821+ SET_MEMORY_INFO_NAME (WorkerCpuUsageTaker)
822+ SET_SELF_SIZE (WorkerCpuUsageTaker)
823+ };
824+
825+ void Worker::CpuUsage (const FunctionCallbackInfo<Value>& args) {
826+ Worker* w;
827+ ASSIGN_OR_RETURN_UNWRAP (&w, args.This ());
828+
829+ Environment* env = w->env ();
830+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope (w);
831+ Local<Object> wrap;
832+ if (!env->worker_cpu_usage_taker_template ()
833+ ->NewInstance (env->context ())
834+ .ToLocal (&wrap)) {
835+ return ;
836+ }
837+
838+ BaseObjectPtr<WorkerCpuUsageTaker> taker =
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+ [taker = std::move (taker),
848+ cpu_usage_stats = std::move (cpu_usage_stats),
849+ err = err](Environment* env) mutable {
850+ Isolate* isolate = env->isolate ();
851+ HandleScope handle_scope (isolate);
852+ Context::Scope context_scope (env->context ());
853+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_id_scope (taker.get ());
854+
855+ Local<Value> argv[] = {
856+ Null (isolate),
857+ Undefined (isolate),
858+ };
859+
860+ if (err) {
861+ argv[0 ] = UVException (
862+ isolate, err, " uv_getrusage_thread" , nullptr , nullptr , nullptr );
863+ } else {
864+ Local<Name> names[] = {
865+ FIXED_ONE_BYTE_STRING (isolate, " user" ),
866+ FIXED_ONE_BYTE_STRING (isolate, " system" ),
867+ };
868+ Local<Value> values[] = {
869+ Number::New (isolate,
870+ 1e6 * cpu_usage_stats->ru_utime .tv_sec +
871+ cpu_usage_stats->ru_utime .tv_usec ),
872+ Number::New (isolate,
873+ 1e6 * cpu_usage_stats->ru_stime .tv_sec +
874+ cpu_usage_stats->ru_stime .tv_usec ),
875+ };
876+ argv[1 ] = Object::New (
877+ isolate, Null (isolate), names, values, arraysize (names));
878+ }
879+
880+ taker->MakeCallback (env->ondone_string (), arraysize (argv), argv);
881+ },
882+ CallbackFlags::kUnrefed );
883+ });
884+
885+ if (scheduled) {
886+ args.GetReturnValue ().Set (wrap);
887+ }
888+ }
889+
814890class WorkerHeapStatisticsTaker : public AsyncWrap {
815891 public:
816892 WorkerHeapStatisticsTaker (Environment* env, Local<Object> obj)
@@ -1102,6 +1178,7 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11021178 SetProtoMethod (isolate, w, " loopIdleTime" , Worker::LoopIdleTime);
11031179 SetProtoMethod (isolate, w, " loopStartTime" , Worker::LoopStartTime);
11041180 SetProtoMethod (isolate, w, " getHeapStatistics" , Worker::GetHeapStatistics);
1181+ SetProtoMethod (isolate, w, " cpuUsage" , Worker::CpuUsage);
11051182
11061183 SetConstructorFunction (isolate, target, " Worker" , w);
11071184 }
@@ -1134,6 +1211,19 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
11341211 wst->InstanceTemplate ());
11351212 }
11361213
1214+ {
1215+ Local<FunctionTemplate> wst = NewFunctionTemplate (isolate, nullptr );
1216+
1217+ wst->InstanceTemplate ()->SetInternalFieldCount (
1218+ WorkerCpuUsageTaker::kInternalFieldCount );
1219+ wst->Inherit (AsyncWrap::GetConstructorTemplate (isolate_data));
1220+
1221+ Local<String> wst_string =
1222+ FIXED_ONE_BYTE_STRING (isolate, " WorkerCpuUsageTaker" );
1223+ wst->SetClassName (wst_string);
1224+ isolate_data->set_worker_cpu_usage_taker_template (wst->InstanceTemplate ());
1225+ }
1226+
11371227 SetMethod (isolate, target, " getEnvMessagePort" , GetEnvMessagePort);
11381228}
11391229
@@ -1200,6 +1290,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
12001290 registry->Register (Worker::LoopIdleTime);
12011291 registry->Register (Worker::LoopStartTime);
12021292 registry->Register (Worker::GetHeapStatistics);
1293+ registry->Register (Worker::CpuUsage);
12031294}
12041295
12051296} // anonymous namespace
0 commit comments