@@ -69,6 +69,7 @@ deno_core::extension!(
69
69
op_get_exit_code,
70
70
op_system_memory_info,
71
71
op_uid,
72
+ op_runtime_cpu_usage,
72
73
op_runtime_memory_usage,
73
74
ops:: signal:: op_signal_bind,
74
75
ops:: signal:: op_signal_unbind,
@@ -106,6 +107,7 @@ deno_core::extension!(
106
107
op_get_exit_code,
107
108
op_system_memory_info,
108
109
op_uid,
110
+ op_runtime_cpu_usage,
109
111
op_runtime_memory_usage,
110
112
ops:: signal:: op_signal_bind,
111
113
ops:: signal:: op_signal_unbind,
@@ -420,27 +422,127 @@ fn op_uid(state: &mut OpState) -> Result<Option<u32>, PermissionCheckError> {
420
422
Ok ( None )
421
423
}
422
424
423
- // HeapStats stores values from a isolate.get_heap_statistics() call
424
- #[ derive( Serialize ) ]
425
- #[ serde( rename_all = "camelCase" ) ]
426
- struct MemoryUsage {
427
- rss : usize ,
428
- heap_total : usize ,
429
- heap_used : usize ,
430
- external : usize ,
425
+ #[ op2]
426
+ #[ serde]
427
+ fn op_runtime_cpu_usage ( ) -> ( usize , usize ) {
428
+ let ( sys, user) = get_cpu_usage ( ) ;
429
+ ( sys. as_micros ( ) as usize , user. as_micros ( ) as usize )
430
+ }
431
+
432
+ #[ cfg( unix) ]
433
+ fn get_cpu_usage ( ) -> ( std:: time:: Duration , std:: time:: Duration ) {
434
+ let mut rusage = std:: mem:: MaybeUninit :: uninit ( ) ;
435
+
436
+ // Uses POSIX getrusage from libc
437
+ // to retrieve user and system times
438
+ // SAFETY: libc call
439
+ let ret = unsafe { libc:: getrusage ( libc:: RUSAGE_SELF , rusage. as_mut_ptr ( ) ) } ;
440
+ if ret != 0 {
441
+ return Default :: default ( ) ;
442
+ }
443
+
444
+ // SAFETY: already checked the result
445
+ let rusage = unsafe { rusage. assume_init ( ) } ;
446
+
447
+ let sys = std:: time:: Duration :: from_micros ( rusage. ru_stime . tv_usec as u64 )
448
+ + std:: time:: Duration :: from_secs ( rusage. ru_stime . tv_sec as u64 ) ;
449
+ let user = std:: time:: Duration :: from_micros ( rusage. ru_utime . tv_usec as u64 )
450
+ + std:: time:: Duration :: from_secs ( rusage. ru_utime . tv_sec as u64 ) ;
451
+
452
+ ( sys, user)
453
+ }
454
+
455
+ #[ cfg( windows) ]
456
+ fn get_cpu_usage ( ) -> ( std:: time:: Duration , std:: time:: Duration ) {
457
+ use winapi:: shared:: minwindef:: FALSE ;
458
+ use winapi:: shared:: minwindef:: FILETIME ;
459
+ use winapi:: shared:: minwindef:: TRUE ;
460
+ use winapi:: um:: minwinbase:: SYSTEMTIME ;
461
+ use winapi:: um:: processthreadsapi:: GetCurrentProcess ;
462
+ use winapi:: um:: processthreadsapi:: GetProcessTimes ;
463
+ use winapi:: um:: timezoneapi:: FileTimeToSystemTime ;
464
+
465
+ fn convert_system_time ( system_time : SYSTEMTIME ) -> std:: time:: Duration {
466
+ std:: time:: Duration :: from_secs (
467
+ system_time. wHour as u64 * 3600
468
+ + system_time. wMinute as u64 * 60
469
+ + system_time. wSecond as u64 ,
470
+ ) + std:: time:: Duration :: from_millis ( system_time. wMilliseconds as u64 )
471
+ }
472
+
473
+ let mut creation_time = std:: mem:: MaybeUninit :: < FILETIME > :: uninit ( ) ;
474
+ let mut exit_time = std:: mem:: MaybeUninit :: < FILETIME > :: uninit ( ) ;
475
+ let mut kernel_time = std:: mem:: MaybeUninit :: < FILETIME > :: uninit ( ) ;
476
+ let mut user_time = std:: mem:: MaybeUninit :: < FILETIME > :: uninit ( ) ;
477
+
478
+ // SAFETY: winapi calls
479
+ let ret = unsafe {
480
+ GetProcessTimes (
481
+ GetCurrentProcess ( ) ,
482
+ creation_time. as_mut_ptr ( ) ,
483
+ exit_time. as_mut_ptr ( ) ,
484
+ kernel_time. as_mut_ptr ( ) ,
485
+ user_time. as_mut_ptr ( ) ,
486
+ )
487
+ } ;
488
+
489
+ if ret != TRUE {
490
+ return std:: default:: Default :: default ( ) ;
491
+ }
492
+
493
+ let mut kernel_system_time = std:: mem:: MaybeUninit :: < SYSTEMTIME > :: uninit ( ) ;
494
+ let mut user_system_time = std:: mem:: MaybeUninit :: < SYSTEMTIME > :: uninit ( ) ;
495
+
496
+ // SAFETY: convert to system time
497
+ unsafe {
498
+ let sys_ret = FileTimeToSystemTime (
499
+ kernel_time. assume_init_mut ( ) ,
500
+ kernel_system_time. as_mut_ptr ( ) ,
501
+ ) ;
502
+ let user_ret = FileTimeToSystemTime (
503
+ user_time. assume_init_mut ( ) ,
504
+ user_system_time. as_mut_ptr ( ) ,
505
+ ) ;
506
+
507
+ match ( sys_ret, user_ret) {
508
+ ( TRUE , TRUE ) => (
509
+ convert_system_time ( kernel_system_time. assume_init ( ) ) ,
510
+ convert_system_time ( user_system_time. assume_init ( ) ) ,
511
+ ) ,
512
+ ( TRUE , FALSE ) => (
513
+ convert_system_time ( kernel_system_time. assume_init ( ) ) ,
514
+ Default :: default ( ) ,
515
+ ) ,
516
+ ( FALSE , TRUE ) => (
517
+ Default :: default ( ) ,
518
+ convert_system_time ( user_system_time. assume_init ( ) ) ,
519
+ ) ,
520
+ ( _, _) => Default :: default ( ) ,
521
+ }
522
+ }
523
+ }
524
+
525
+ #[ cfg( not( any( windows, unix) ) ) ]
526
+ fn get_cpu_usage ( ) -> ( std:: time:: Duration , std:: time:: Duration ) {
527
+ Default :: default ( )
431
528
}
432
529
433
530
#[ op2]
434
531
#[ serde]
435
- fn op_runtime_memory_usage ( scope : & mut v8:: HandleScope ) -> MemoryUsage {
532
+ fn op_runtime_memory_usage (
533
+ scope : & mut v8:: HandleScope ,
534
+ ) -> ( usize , usize , usize , usize ) {
436
535
let mut s = v8:: HeapStatistics :: default ( ) ;
437
536
scope. get_heap_statistics ( & mut s) ;
438
- MemoryUsage {
439
- rss : rss ( ) ,
440
- heap_total : s. total_heap_size ( ) ,
441
- heap_used : s. used_heap_size ( ) ,
442
- external : s. external_memory ( ) ,
443
- }
537
+
538
+ let ( rss, heap_total, heap_used, external) = (
539
+ rss ( ) ,
540
+ s. total_heap_size ( ) ,
541
+ s. used_heap_size ( ) ,
542
+ s. external_memory ( ) ,
543
+ ) ;
544
+
545
+ ( rss, heap_total, heap_used, external)
444
546
}
445
547
446
548
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
0 commit comments