mirror of
https://github.com/denoland/deno.git
synced 2025-02-08 07:16:56 -05:00
feat: implement process.cpuUsage
(Deno.cpuUsage
) (#27217)
This commit is contained in:
parent
b7456fed70
commit
e6dda60d5c
4 changed files with 136 additions and 21 deletions
|
@ -441,11 +441,7 @@ Process.prototype.config = {
|
|||
};
|
||||
|
||||
Process.prototype.cpuUsage = function () {
|
||||
warnNotImplemented("process.cpuUsage()");
|
||||
return {
|
||||
user: 0,
|
||||
system: 0,
|
||||
};
|
||||
return Deno.cpuUsage();
|
||||
};
|
||||
|
||||
/** https://nodejs.org/api/process.html#process_process_cwd */
|
||||
|
|
|
@ -32,3 +32,11 @@ This crate implements OS specific APIs for Deno
|
|||
| Linux | sysinfo and `/proc/meminfo` | - |
|
||||
| Windows | `sysinfoapi::GlobalMemoryStatusEx` | - |
|
||||
| macOS | <br> <pre> sysctl([CTL_HW, HW_MEMSIZE]); <br> sysctl([CTL_VM, VM_SWAPUSAGE]); <br> host_statistics64(mach_host_self(), HOST_VM_INFO64) </pre> | - |
|
||||
|
||||
`cpu_usage`
|
||||
|
||||
| Target family | Syscall | Description |
|
||||
| ------------- | ------------------------------------ | ----------- |
|
||||
| Linux | getrusage | - |
|
||||
| Windows | `processthreadsapi::GetProcessTimes` | - |
|
||||
| macOS | getrusage | - |
|
||||
|
|
132
ext/os/lib.rs
132
ext/os/lib.rs
|
@ -69,6 +69,7 @@ deno_core::extension!(
|
|||
op_get_exit_code,
|
||||
op_system_memory_info,
|
||||
op_uid,
|
||||
op_runtime_cpu_usage,
|
||||
op_runtime_memory_usage,
|
||||
ops::signal::op_signal_bind,
|
||||
ops::signal::op_signal_unbind,
|
||||
|
@ -106,6 +107,7 @@ deno_core::extension!(
|
|||
op_get_exit_code,
|
||||
op_system_memory_info,
|
||||
op_uid,
|
||||
op_runtime_cpu_usage,
|
||||
op_runtime_memory_usage,
|
||||
ops::signal::op_signal_bind,
|
||||
ops::signal::op_signal_unbind,
|
||||
|
@ -420,27 +422,127 @@ fn op_uid(state: &mut OpState) -> Result<Option<u32>, PermissionCheckError> {
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
// HeapStats stores values from a isolate.get_heap_statistics() call
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct MemoryUsage {
|
||||
rss: usize,
|
||||
heap_total: usize,
|
||||
heap_used: usize,
|
||||
external: usize,
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_runtime_cpu_usage() -> (usize, usize) {
|
||||
let (sys, user) = get_cpu_usage();
|
||||
(sys.as_micros() as usize, user.as_micros() as usize)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn get_cpu_usage() -> (std::time::Duration, std::time::Duration) {
|
||||
let mut rusage = std::mem::MaybeUninit::uninit();
|
||||
|
||||
// Uses POSIX getrusage from libc
|
||||
// to retrieve user and system times
|
||||
// SAFETY: libc call
|
||||
let ret = unsafe { libc::getrusage(libc::RUSAGE_SELF, rusage.as_mut_ptr()) };
|
||||
if ret != 0 {
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
// SAFETY: already checked the result
|
||||
let rusage = unsafe { rusage.assume_init() };
|
||||
|
||||
let sys = std::time::Duration::from_micros(rusage.ru_stime.tv_usec as u64)
|
||||
+ std::time::Duration::from_secs(rusage.ru_stime.tv_sec as u64);
|
||||
let user = std::time::Duration::from_micros(rusage.ru_utime.tv_usec as u64)
|
||||
+ std::time::Duration::from_secs(rusage.ru_utime.tv_sec as u64);
|
||||
|
||||
(sys, user)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn get_cpu_usage() -> (std::time::Duration, std::time::Duration) {
|
||||
use winapi::shared::minwindef::FALSE;
|
||||
use winapi::shared::minwindef::FILETIME;
|
||||
use winapi::shared::minwindef::TRUE;
|
||||
use winapi::um::minwinbase::SYSTEMTIME;
|
||||
use winapi::um::processthreadsapi::GetCurrentProcess;
|
||||
use winapi::um::processthreadsapi::GetProcessTimes;
|
||||
use winapi::um::timezoneapi::FileTimeToSystemTime;
|
||||
|
||||
fn convert_system_time(system_time: SYSTEMTIME) -> std::time::Duration {
|
||||
std::time::Duration::from_secs(
|
||||
system_time.wHour as u64 * 3600
|
||||
+ system_time.wMinute as u64 * 60
|
||||
+ system_time.wSecond as u64,
|
||||
) + std::time::Duration::from_millis(system_time.wMilliseconds as u64)
|
||||
}
|
||||
|
||||
let mut creation_time = std::mem::MaybeUninit::<FILETIME>::uninit();
|
||||
let mut exit_time = std::mem::MaybeUninit::<FILETIME>::uninit();
|
||||
let mut kernel_time = std::mem::MaybeUninit::<FILETIME>::uninit();
|
||||
let mut user_time = std::mem::MaybeUninit::<FILETIME>::uninit();
|
||||
|
||||
// SAFETY: winapi calls
|
||||
let ret = unsafe {
|
||||
GetProcessTimes(
|
||||
GetCurrentProcess(),
|
||||
creation_time.as_mut_ptr(),
|
||||
exit_time.as_mut_ptr(),
|
||||
kernel_time.as_mut_ptr(),
|
||||
user_time.as_mut_ptr(),
|
||||
)
|
||||
};
|
||||
|
||||
if ret != TRUE {
|
||||
return std::default::Default::default();
|
||||
}
|
||||
|
||||
let mut kernel_system_time = std::mem::MaybeUninit::<SYSTEMTIME>::uninit();
|
||||
let mut user_system_time = std::mem::MaybeUninit::<SYSTEMTIME>::uninit();
|
||||
|
||||
// SAFETY: convert to system time
|
||||
unsafe {
|
||||
let sys_ret = FileTimeToSystemTime(
|
||||
kernel_time.assume_init_mut(),
|
||||
kernel_system_time.as_mut_ptr(),
|
||||
);
|
||||
let user_ret = FileTimeToSystemTime(
|
||||
user_time.assume_init_mut(),
|
||||
user_system_time.as_mut_ptr(),
|
||||
);
|
||||
|
||||
match (sys_ret, user_ret) {
|
||||
(TRUE, TRUE) => (
|
||||
convert_system_time(kernel_system_time.assume_init()),
|
||||
convert_system_time(user_system_time.assume_init()),
|
||||
),
|
||||
(TRUE, FALSE) => (
|
||||
convert_system_time(kernel_system_time.assume_init()),
|
||||
Default::default(),
|
||||
),
|
||||
(FALSE, TRUE) => (
|
||||
Default::default(),
|
||||
convert_system_time(user_system_time.assume_init()),
|
||||
),
|
||||
(_, _) => Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, unix)))]
|
||||
fn get_cpu_usage() -> (std::time::Duration, std::time::Duration) {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_runtime_memory_usage(scope: &mut v8::HandleScope) -> MemoryUsage {
|
||||
fn op_runtime_memory_usage(
|
||||
scope: &mut v8::HandleScope,
|
||||
) -> (usize, usize, usize, usize) {
|
||||
let mut s = v8::HeapStatistics::default();
|
||||
scope.get_heap_statistics(&mut s);
|
||||
MemoryUsage {
|
||||
rss: rss(),
|
||||
heap_total: s.total_heap_size(),
|
||||
heap_used: s.used_heap_size(),
|
||||
external: s.external_memory(),
|
||||
}
|
||||
|
||||
let (rss, heap_total, heap_used, external) = (
|
||||
rss(),
|
||||
s.total_heap_size(),
|
||||
s.used_heap_size(),
|
||||
s.external_memory(),
|
||||
);
|
||||
|
||||
(rss, heap_total, heap_used, external)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
|
|
|
@ -4,6 +4,7 @@ import { core, primordials } from "ext:core/mod.js";
|
|||
import {
|
||||
op_net_listen_udp,
|
||||
op_net_listen_unixpacket,
|
||||
op_runtime_cpu_usage,
|
||||
op_runtime_memory_usage,
|
||||
} from "ext:core/ops";
|
||||
|
||||
|
@ -59,7 +60,15 @@ const denoNs = {
|
|||
makeTempDir: fs.makeTempDir,
|
||||
makeTempFileSync: fs.makeTempFileSync,
|
||||
makeTempFile: fs.makeTempFile,
|
||||
memoryUsage: () => op_runtime_memory_usage(),
|
||||
cpuUsage: () => {
|
||||
const { 0: system, 1: user } = op_runtime_cpu_usage();
|
||||
return { system, user };
|
||||
},
|
||||
memoryUsage: () => {
|
||||
const { 0: rss, 1: heapTotal, 2: heapUsed, 3: external } =
|
||||
op_runtime_memory_usage();
|
||||
return { rss, heapTotal, heapUsed, external };
|
||||
},
|
||||
mkdirSync: fs.mkdirSync,
|
||||
mkdir: fs.mkdir,
|
||||
chdir: fs.chdir,
|
||||
|
|
Loading…
Add table
Reference in a new issue