@@ -25,7 +25,7 @@ class WaitForProcessWorker : public Napi::AsyncWorker {
2525public:
2626 WaitForProcessWorker (Napi::Env &env, pid_t pid, uint32_t timeoutMs, uint64_t memoryLimitBytes)
2727 : Napi::AsyncWorker(env), pid_(pid), timeoutMs_(timeoutMs),
28- memoryLimitBytes_ (memoryLimitBytes), deferred_(env), elapsedMs_(0.0 ), cpuMs_( 0.0 ), peakMemoryBytes_(0 ),
28+ memoryLimitBytes_ (memoryLimitBytes), deferred_(env), elapsedMs_(0.0 ), peakMemoryBytes_(0 ),
2929 exitCode_(0 ), timedOut_(false ), memoryLimitExceeded_(false ), stopped_(false ), errorMsg_(" " ) {}
3030
3131 Napi::Promise GetPromise () { return deferred_.Promise (); }
@@ -124,15 +124,10 @@ class WaitForProcessWorker : public Napi::AsyncWorker {
124124 struct timeval endTime;
125125 gettimeofday (&endTime, nullptr );
126126
127- // Calculate elapsed wall-clock time
128- elapsedUs = (endTime.tv_sec - startTime.tv_sec ) * 1000000ULL +
129- (endTime.tv_usec - startTime.tv_usec );
130- elapsedMs_ = static_cast <double >(elapsedUs) / 1000.0 ;
131-
132- // Calculate CPU time from rusage
127+ // Calculate elapsed CPU time from rusage (user + system)
133128 uint64_t cpuUs = (rusage.ru_utime .tv_sec + rusage.ru_stime .tv_sec ) * 1000000ULL +
134129 (rusage.ru_utime .tv_usec + rusage.ru_stime .tv_usec );
135- cpuMs_ = static_cast <double >(cpuUs) / 1000.0 ;
130+ elapsedMs_ = static_cast <double >(cpuUs) / 1000.0 ;
136131
137132 // Get peak memory (in kilobytes on Linux, convert to bytes)
138133 peakMemoryBytes_ = static_cast <uint64_t >(rusage.ru_maxrss ) * 1024ULL ;
@@ -157,7 +152,6 @@ class WaitForProcessWorker : public Napi::AsyncWorker {
157152
158153 Napi::Object result = Napi::Object::New (env);
159154 result.Set (" elapsedMs" , Napi::Number::New (env, elapsedMs_));
160- result.Set (" cpuMs" , Napi::Number::New (env, cpuMs_));
161155 result.Set (" peakMemoryBytes" , Napi::Number::New (env, static_cast <double >(peakMemoryBytes_)));
162156 result.Set (" exitCode" , Napi::Number::New (env, exitCode_));
163157 result.Set (" timedOut" , Napi::Boolean::New (env, timedOut_));
@@ -177,7 +171,6 @@ class WaitForProcessWorker : public Napi::AsyncWorker {
177171 uint64_t memoryLimitBytes_;
178172 Napi::Promise::Deferred deferred_;
179173 double elapsedMs_;
180- double cpuMs_;
181174 uint64_t peakMemoryBytes_;
182175 int exitCode_;
183176 bool timedOut_;
@@ -302,66 +295,6 @@ bool ReadSystemUptime(double &uptimeSeconds, std::string &err) {
302295 return true ;
303296}
304297
305- // Keep the synchronous version for compatibility
306- Napi::Value GetLinuxProcessTimes (const Napi::CallbackInfo &info) {
307- Napi::Env env = info.Env ();
308-
309- if (info.Length () < 1 ) {
310- Napi::TypeError::New (env, " PID argument is required" )
311- .ThrowAsJavaScriptException ();
312- return env.Null ();
313- }
314- if (!info[0 ].IsNumber ()) {
315- Napi::TypeError::New (env, " PID must be a number" )
316- .ThrowAsJavaScriptException ();
317- return env.Null ();
318- }
319-
320- uint32_t pid = info[0 ].As <Napi::Number>().Uint32Value ();
321-
322- if (pid < 1 || pid > 4194304 ) {
323- Napi::RangeError::New (env, " PID is out of range" )
324- .ThrowAsJavaScriptException ();
325- return env.Null ();
326- }
327-
328- uint64_t startTimeJiffies = 0 ;
329- uint64_t utimeJiffies = 0 ;
330- uint64_t stimeJiffies = 0 ;
331- std::string err;
332- if (!ReadProcStat (pid, startTimeJiffies, utimeJiffies, stimeJiffies, err)) {
333- Napi::Error::New (env, err).ThrowAsJavaScriptException ();
334- return env.Null ();
335- }
336-
337- double systemUptimeSeconds = 0.0 ;
338- if (!ReadSystemUptime (systemUptimeSeconds, err)) {
339- Napi::Error::New (env, err).ThrowAsJavaScriptException ();
340- return env.Null ();
341- }
342-
343- long clockTicksPerSecond = sysconf (_SC_CLK_TCK);
344- if (clockTicksPerSecond <= 0 ) {
345- Napi::Error::New (env, " Failed to get _SC_CLK_TCK" )
346- .ThrowAsJavaScriptException ();
347- return env.Null ();
348- }
349-
350- double processStartSeconds =
351- static_cast <double >(startTimeJiffies) / clockTicksPerSecond;
352- double elapsedSeconds = systemUptimeSeconds - processStartSeconds;
353- double elapsedMs = elapsedSeconds * 1000.0 ;
354-
355- double cpuSeconds = static_cast <double >(utimeJiffies + stimeJiffies) /
356- clockTicksPerSecond;
357- double cpuMs = cpuSeconds * 1000.0 ;
358-
359- Napi::Object result = Napi::Object::New (env);
360- result.Set (" elapsedMs" , Napi::Number::New (env, elapsedMs));
361- result.Set (" cpuMs" , Napi::Number::New (env, cpuMs));
362- return result;
363- }
364-
365298// Helper to parse memory lines from /proc/<pid>/status
366299bool ParseKbLineToBytes (const char *line, const char *prefix,
367300 uint64_t &outBytes) {
@@ -447,7 +380,8 @@ bool ReadProcStatusMemory(uint32_t pid, uint64_t &rssBytes, uint64_t &peakRssByt
447380 return true ;
448381}
449382
450- Napi::Value GetLinuxMemoryStats (const Napi::CallbackInfo &info) {
383+ // Combined function to get process stats (elapsed CPU time and memory)
384+ Napi::Value GetLinuxProcessStats (const Napi::CallbackInfo &info) {
451385 Napi::Env env = info.Env ();
452386
453387 if (info.Length () < 1 ) {
@@ -469,15 +403,38 @@ Napi::Value GetLinuxMemoryStats(const Napi::CallbackInfo &info) {
469403 return env.Null ();
470404 }
471405
406+ // Get CPU times from /proc/<pid>/stat
407+ uint64_t startTimeJiffies = 0 ;
408+ uint64_t utimeJiffies = 0 ;
409+ uint64_t stimeJiffies = 0 ;
410+ std::string err;
411+ if (!ReadProcStat (pid, startTimeJiffies, utimeJiffies, stimeJiffies, err)) {
412+ Napi::Error::New (env, err).ThrowAsJavaScriptException ();
413+ return env.Null ();
414+ }
415+
416+ long clockTicksPerSecond = sysconf (_SC_CLK_TCK);
417+ if (clockTicksPerSecond <= 0 ) {
418+ Napi::Error::New (env, " Failed to get _SC_CLK_TCK" )
419+ .ThrowAsJavaScriptException ();
420+ return env.Null ();
421+ }
422+
423+ // Calculate elapsed CPU time (user + system)
424+ double cpuSeconds = static_cast <double >(utimeJiffies + stimeJiffies) /
425+ clockTicksPerSecond;
426+ double elapsedMs = cpuSeconds * 1000.0 ;
427+
428+ // Get memory stats from /proc/<pid>/status
472429 uint64_t rssBytes = 0 ;
473430 uint64_t peakRssBytes = 0 ;
474- std::string err;
475431 if (!ReadProcStatusMemory (pid, rssBytes, peakRssBytes, err)) {
476432 Napi::Error::New (env, err).ThrowAsJavaScriptException ();
477433 return env.Null ();
478434 }
479435
480436 Napi::Object result = Napi::Object::New (env);
437+ result.Set (" elapsedMs" , Napi::Number::New (env, elapsedMs));
481438 result.Set (" rss" , Napi::Number::New (env, static_cast <double >(rssBytes)));
482439 result.Set (" peakRss" ,
483440 Napi::Number::New (env, static_cast <double >(peakRssBytes)));
@@ -487,12 +444,9 @@ Napi::Value GetLinuxMemoryStats(const Napi::CallbackInfo &info) {
487444Napi::Object Init (Napi::Env env, Napi::Object exports) {
488445 exports.Set (" waitForProcess" ,
489446 Napi::Function::New (env, WaitForProcess, " waitForProcess" ));
490- exports.Set (" getLinuxProcessTimes" ,
491- Napi::Function::New (env, GetLinuxProcessTimes,
492- " getLinuxProcessTimes" ));
493- exports.Set (" getLinuxMemoryStats" ,
494- Napi::Function::New (env, GetLinuxMemoryStats,
495- " getLinuxMemoryStats" ));
447+ exports.Set (" getLinuxProcessStats" ,
448+ Napi::Function::New (env, GetLinuxProcessStats,
449+ " getLinuxProcessStats" ));
496450 return exports;
497451}
498452
0 commit comments