@@ -32,6 +32,7 @@ using v8::Isolate;
32
32
using v8::Local;
33
33
using v8::Locker;
34
34
using v8::Maybe;
35
+ using v8::Name;
35
36
using v8::Null;
36
37
using v8::Number;
37
38
using v8::Object;
@@ -810,6 +811,81 @@ void Worker::Unref(const FunctionCallbackInfo<Value>& args) {
810
811
}
811
812
}
812
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
+ 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
+
813
889
class WorkerHeapStatisticsTaker : public AsyncWrap {
814
890
public:
815
891
WorkerHeapStatisticsTaker (Environment* env, Local<Object> obj)
@@ -1101,6 +1177,7 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
1101
1177
SetProtoMethod (isolate, w, " loopIdleTime" , Worker::LoopIdleTime);
1102
1178
SetProtoMethod (isolate, w, " loopStartTime" , Worker::LoopStartTime);
1103
1179
SetProtoMethod (isolate, w, " getHeapStatistics" , Worker::GetHeapStatistics);
1180
+ SetProtoMethod (isolate, w, " cpuUsage" , Worker::CpuUsage);
1104
1181
1105
1182
SetConstructorFunction (isolate, target, " Worker" , w);
1106
1183
}
@@ -1133,6 +1210,19 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
1133
1210
wst->InstanceTemplate ());
1134
1211
}
1135
1212
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
+
1136
1226
SetMethod (isolate, target, " getEnvMessagePort" , GetEnvMessagePort);
1137
1227
}
1138
1228
@@ -1199,6 +1289,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1199
1289
registry->Register (Worker::LoopIdleTime);
1200
1290
registry->Register (Worker::LoopStartTime);
1201
1291
registry->Register (Worker::GetHeapStatistics);
1292
+ registry->Register (Worker::CpuUsage);
1202
1293
}
1203
1294
1204
1295
} // anonymous namespace
0 commit comments