@@ -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;
@@ -811,6 +812,81 @@ void Worker::Unref(const FunctionCallbackInfo<Value>& args) {
811
812
}
812
813
}
813
814
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
+
814
890
class WorkerHeapStatisticsTaker : public AsyncWrap {
815
891
public:
816
892
WorkerHeapStatisticsTaker (Environment* env, Local<Object> obj)
@@ -1102,6 +1178,7 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
1102
1178
SetProtoMethod (isolate, w, " loopIdleTime" , Worker::LoopIdleTime);
1103
1179
SetProtoMethod (isolate, w, " loopStartTime" , Worker::LoopStartTime);
1104
1180
SetProtoMethod (isolate, w, " getHeapStatistics" , Worker::GetHeapStatistics);
1181
+ SetProtoMethod (isolate, w, " cpuUsage" , Worker::CpuUsage);
1105
1182
1106
1183
SetConstructorFunction (isolate, target, " Worker" , w);
1107
1184
}
@@ -1134,6 +1211,19 @@ void CreateWorkerPerIsolateProperties(IsolateData* isolate_data,
1134
1211
wst->InstanceTemplate ());
1135
1212
}
1136
1213
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
+
1137
1227
SetMethod (isolate, target, " getEnvMessagePort" , GetEnvMessagePort);
1138
1228
}
1139
1229
@@ -1200,6 +1290,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1200
1290
registry->Register (Worker::LoopIdleTime);
1201
1291
registry->Register (Worker::LoopStartTime);
1202
1292
registry->Register (Worker::GetHeapStatistics);
1293
+ registry->Register (Worker::CpuUsage);
1203
1294
}
1204
1295
1205
1296
} // anonymous namespace
0 commit comments