mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 16:33:37 +01:00
* Fix ps command CPU usage on Apple Silicon M1 macs. #4142 The cpu user and system times returned my libproc are not in nanoseconds; they are in mach ticks units. This is not documented very well. The convert from mach ticks to ns, the kernel provides a timebase info function and datatype: https://developer.apple.com/documentation/driverkit/3433733-mach_timebase_info The commit makes the PS command work for me. * Cargo fmt of previous commit. * Clippy format suggestion Co-authored-by: Ondrej Baudys <ondrej.baudys@nextgen.net>
This commit is contained in:
parent
b27148d14b
commit
e266590813
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2219,6 +2219,15 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mach2"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "malloc_buf"
|
name = "malloc_buf"
|
||||||
version = "0.0.6"
|
version = "0.0.6"
|
||||||
@ -2863,6 +2872,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"libproc",
|
"libproc",
|
||||||
|
"mach2",
|
||||||
"nix",
|
"nix",
|
||||||
"ntapi",
|
"ntapi",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -26,6 +26,7 @@ procfs = "0.14.0"
|
|||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
libproc = "0.12.0"
|
libproc = "0.12.0"
|
||||||
errno = "0.2"
|
errno = "0.2"
|
||||||
|
mach2 = "0.4"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
winapi = { version = "0.3.9", features = ["tlhelp32", "fileapi", "handleapi", "ifdef", "ioapiset", "minwindef", "pdh", "psapi", "synchapi", "sysinfoapi", "winbase", "winerror", "winioctl", "winnt", "oleauto", "wbemcli", "rpcdce", "combaseapi", "objidl", "powerbase", "netioapi", "lmcons", "lmaccess", "lmapibuf", "memoryapi", "shellapi", "std", "securitybaseapi"] }
|
winapi = { version = "0.3.9", features = ["tlhelp32", "fileapi", "handleapi", "ifdef", "ioapiset", "minwindef", "pdh", "psapi", "synchapi", "sysinfoapi", "winbase", "winerror", "winioctl", "winnt", "oleauto", "wbemcli", "rpcdce", "combaseapi", "objidl", "powerbase", "netioapi", "lmcons", "lmaccess", "lmapibuf", "memoryapi", "shellapi", "std", "securitybaseapi"] }
|
||||||
|
@ -6,6 +6,7 @@ use libproc::libproc::pid_rusage::{pidrusage, RUsageInfoV2};
|
|||||||
use libproc::libproc::proc_pid::{listpidinfo, listpids, pidinfo, ListThreads, ProcType};
|
use libproc::libproc::proc_pid::{listpidinfo, listpids, pidinfo, ListThreads, ProcType};
|
||||||
use libproc::libproc::task_info::{TaskAllInfo, TaskInfo};
|
use libproc::libproc::task_info::{TaskAllInfo, TaskInfo};
|
||||||
use libproc::libproc::thread_info::ThreadInfo;
|
use libproc::libproc::thread_info::ThreadInfo;
|
||||||
|
use mach2::mach_time;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -372,9 +373,10 @@ impl ProcessInfo {
|
|||||||
self.curr_task.ptinfo.pti_total_user + self.curr_task.ptinfo.pti_total_system;
|
self.curr_task.ptinfo.pti_total_user + self.curr_task.ptinfo.pti_total_system;
|
||||||
let prev_time =
|
let prev_time =
|
||||||
self.prev_task.ptinfo.pti_total_user + self.prev_task.ptinfo.pti_total_system;
|
self.prev_task.ptinfo.pti_total_user + self.prev_task.ptinfo.pti_total_system;
|
||||||
let usage_ms = (curr_time - prev_time) / 1000000u64;
|
let usage_ticks = curr_time - prev_time;
|
||||||
let interval_ms = self.interval.as_secs() * 1000 + u64::from(self.interval.subsec_millis());
|
let interval_us = self.interval.as_micros();
|
||||||
usage_ms as f64 * 100.0 / interval_ms as f64
|
let ticktime_us = mach_ticktime() / 1000.0;
|
||||||
|
usage_ticks as f64 * 100.0 * ticktime_us / interval_us as f64
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Memory size in number of bytes
|
/// Memory size in number of bytes
|
||||||
@ -387,3 +389,18 @@ impl ProcessInfo {
|
|||||||
self.curr_task.ptinfo.pti_virtual_size
|
self.curr_task.ptinfo.pti_virtual_size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The Macos kernel returns process times in mach ticks rather than nanoseconds. To get times in
|
||||||
|
/// nanoseconds, we need to multiply by the mach timebase, a fractional value reported by the
|
||||||
|
/// kernel. It is uncertain if the kernel returns the same value on each call to
|
||||||
|
/// mach_timebase_info; if it does, it may be worth reimplementing this as a lazy_static value.
|
||||||
|
fn mach_ticktime() -> f64 {
|
||||||
|
let mut timebase = mach_time::mach_timebase_info_data_t::default();
|
||||||
|
let err = unsafe { mach_time::mach_timebase_info(&mut timebase) };
|
||||||
|
if err == 0 {
|
||||||
|
timebase.numer as f64 / timebase.denom as f64
|
||||||
|
} else {
|
||||||
|
// assume times are in nanoseconds then...
|
||||||
|
1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user