From 2ecf9dfab535032fa6d30a0b7f3be9beabb6b3c5 Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Sat, 25 Jan 2020 21:53:38 -0600 Subject: [PATCH 01/28] support for process disk r/w bytes for linux --- src/linux/process.rs | 4 ++++ src/linux/system.rs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/linux/process.rs b/src/linux/process.rs index f0eb02795..11dd8c42b 100644 --- a/src/linux/process.rs +++ b/src/linux/process.rs @@ -124,6 +124,8 @@ pub struct Process { /// Tasks run by this process. pub tasks: HashMap, pub(crate) stat_file: Option, + pub read_bytes: u64, + pub write_bytes: u64 } impl ProcessExt for Process { @@ -155,6 +157,8 @@ impl ProcessExt for Process { HashMap::new() }, stat_file: None, + read_bytes: 0, + write_bytes: 0 } } diff --git a/src/linux/system.rs b/src/linux/system.rs index 7c23dc223..c515be86d 100644 --- a/src/linux/system.rs +++ b/src/linux/system.rs @@ -738,6 +738,7 @@ fn _get_process_data( uptime, now, ); + update_process_disk_activity(entry); return Ok(None); } @@ -821,9 +822,27 @@ fn _get_process_data( uptime, now, ); + update_process_disk_activity(&mut p); Ok(Some(p)) } +fn update_process_disk_activity(p: &mut Process){ + let path = PathBuf::from(format!("/proc/{}/io", p.pid)); + let data = match get_all_data(&path, 16_384){ + Ok(d) => d, + Err(_) => return + }; + let data: Vec> = data.split("\n").map(|l| l.split(": ").collect()).collect(); + for d in data.iter(){ + if d[0] == "read_bytes"{ + p.read_bytes = d[1].parse::().unwrap_or(0); + } + else if d[0] == "write_bytes"{ + p.write_bytes = d[1].parse::().unwrap_or(0); + } + } +} + fn copy_from_file(entry: &Path) -> Vec { match File::open(entry.to_str().unwrap_or("/")) { Ok(mut f) => { From 08d2c93b10d775370e24bfbdade3be74cc88d010 Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Sat, 25 Jan 2020 22:01:47 -0600 Subject: [PATCH 02/28] update disk usage for mac processes --- src/mac/ffi.rs | 30 ++++++++++++++++++++++++++++++ src/mac/process.rs | 25 ++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/mac/ffi.rs b/src/mac/ffi.rs index f3e0223ae..236788b93 100644 --- a/src/mac/ffi.rs +++ b/src/mac/ffi.rs @@ -130,6 +130,11 @@ extern "C" { // pub fn proc_name(pid: i32, buf: *mut i8, bufsize: u32) -> i32; } +#[link(name = "proc", kind = "dylib")] +extern { + pub fn proc_pid_rusage(pid: c_int, flavor: c_int, buffer: *mut c_void) -> c_int; +} + // TODO: waiting for https://github.com/rust-lang/libc/pull/678 macro_rules! cfg_if { ($( @@ -431,6 +436,31 @@ pub struct xsw_usage { pub xsu_encrypted: boolean_t, } +//https://github.com/andrewdavidmackenzie/libproc-rs/blob/master/src/libproc/pid_rusage.rs +#[repr(C)] +#[derive(Debug, Default)] +pub struct RUsageInfoV2 { + pub ri_uuid : [u8; 16], + pub ri_user_time : u64, + pub ri_system_time : u64, + pub ri_pkg_idle_wkups : u64, + pub ri_interrupt_wkups : u64, + pub ri_pageins : u64, + pub ri_wired_size : u64, + pub ri_resident_size : u64, + pub ri_phys_footprint : u64, + pub ri_proc_start_abstime : u64, + pub ri_proc_exit_abstime : u64, + pub ri_child_user_time : u64, + pub ri_child_system_time : u64, + pub ri_child_pkg_idle_wkups : u64, + pub ri_child_interrupt_wkups: u64, + pub ri_child_pageins : u64, + pub ri_child_elapsed_abstime: u64, + pub ri_diskio_bytesread : u64, + pub ri_diskio_byteswritten : u64, +} + //pub const HOST_CPU_LOAD_INFO_COUNT: usize = 4; //pub const HOST_CPU_LOAD_INFO: u32 = 3; pub const KERN_SUCCESS: kern_return_t = 0; diff --git a/src/mac/process.rs b/src/mac/process.rs index 56556ada5..c32a2f58c 100644 --- a/src/mac/process.rs +++ b/src/mac/process.rs @@ -149,6 +149,9 @@ pub struct Process { /// /// This is very likely this one that you want instead of `process_status`. pub status: Option, + pub read_bytes: u64, + pub write_bytes: u64 + } } impl Process { @@ -175,6 +178,8 @@ impl Process { gid: 0, process_status: ProcessStatus::Unknown(0), status: None, + read_bytes: 0, + write_bytes: 0 } } @@ -384,6 +389,7 @@ pub(crate) fn update_process( p.memory = task_info.pti_resident_size >> 10; // divide by 1024 p.virtual_memory = task_info.pti_virtual_size >> 10; // divide by 1024 + update_proc_disk_activity(&mut p); return Ok(None); } @@ -572,11 +578,28 @@ pub(crate) fn update_process( p.uid = info.pbi_uid; p.gid = info.pbi_gid; p.process_status = ProcessStatus::from(info.pbi_status); - + update_proc_disk_activity(p); Ok(Some(p)) } } +fn update_proc_disk_activity(p: &mut Process){ + let mut pidrusage = ffi::RUsageInfoV2::default(); + let ptr = &mut pidrusage as *mut _ as *mut c_void; + let retval: i32; + unsafe{ + retval = ffi::proc_pid_rusage(p.pid() as c_int, 2, ptr); + } + + if retval < 0{ + panic!("proc_pid_rusage failed: {:?}", retval); + } + else{ + p.read_bytes = pidrusage.ri_diskio_bytesread; + p.write_bytes = pidrusage.ri_diskio_byteswritten; + } +} + pub(crate) fn get_proc_list() -> Option> { let count = unsafe { ffi::proc_listallpids(::std::ptr::null_mut(), 0) }; if count < 1 { From e9ea2617b270dbdb1b4d684b855d673729a52631 Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Sat, 25 Jan 2020 22:11:37 -0600 Subject: [PATCH 03/28] fixed mac compilation issues --- src/mac/process.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/mac/process.rs b/src/mac/process.rs index c32a2f58c..ad560c1d0 100644 --- a/src/mac/process.rs +++ b/src/mac/process.rs @@ -151,7 +151,6 @@ pub struct Process { pub status: Option, pub read_bytes: u64, pub write_bytes: u64 - } } impl Process { @@ -215,6 +214,8 @@ impl Process { gid: 0, process_status: ProcessStatus::Unknown(0), status: None, + read_bytes: 0, + write_bytes: 0 } } } @@ -243,6 +244,8 @@ impl ProcessExt for Process { gid: 0, process_status: ProcessStatus::Unknown(0), status: None, + read_bytes: 0, + write_bytes: 0 } } @@ -389,7 +392,7 @@ pub(crate) fn update_process( p.memory = task_info.pti_resident_size >> 10; // divide by 1024 p.virtual_memory = task_info.pti_virtual_size >> 10; // divide by 1024 - update_proc_disk_activity(&mut p); + update_proc_disk_activity(p); return Ok(None); } @@ -578,7 +581,7 @@ pub(crate) fn update_process( p.uid = info.pbi_uid; p.gid = info.pbi_gid; p.process_status = ProcessStatus::from(info.pbi_status); - update_proc_disk_activity(p); + update_proc_disk_activity(&mut p); Ok(Some(p)) } } From 2619090e9c2a498d45776892579e2845c94e114e Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Sun, 26 Jan 2020 19:30:59 -0600 Subject: [PATCH 04/28] added windows support --- Cargo.toml | 1 + src/sysinfo.rs | 1 + src/windows/process.rs | 48 +++++++++++++++++++++++++++++++++++++++++- src/windows/system.rs | 4 +++- tests/process.rs | 22 +++++++++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0f171f2b7..892f8e7ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ once_cell = "1.0" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["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"] } ntapi = "0.3" +winrt = { version = "0.6.0", features = ["windows-system"]} [target.'cfg(not(any(target_os = "unknown", target_arch = "wasm32")))'.dependencies] libc = "0.2" diff --git a/src/sysinfo.rs b/src/sysinfo.rs index 12fae02d5..409fe489b 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -76,6 +76,7 @@ cfg_if! { #[cfg(test)] const MIN_USERS: usize = 1; + extern crate winrt; } else if #[cfg(unix)] { mod linux; use linux as sys; diff --git a/src/windows/process.rs b/src/windows/process.rs index cffac2d16..e7a4329db 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -28,7 +28,12 @@ use winapi::um::psapi::{ LIST_MODULES_ALL, PROCESS_MEMORY_COUNTERS, PROCESS_MEMORY_COUNTERS_EX, }; use winapi::um::sysinfoapi::GetSystemTimeAsFileTime; -use winapi::um::winnt::{HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ, ULARGE_INTEGER}; +use winapi::um::winnt::{ + HANDLE, /*, PWSTR*/ PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ, + ULARGE_INTEGER, /*THREAD_GET_CONTEXT, THREAD_QUERY_INFORMATION, THREAD_SUSPEND_RESUME,*/ +}; +use winrt::*; +use winrt::windows::system::diagnostics::*; /// Enum describing the different status of a process. #[derive(Clone, Copy, Debug)] @@ -100,6 +105,8 @@ pub struct Process { start_time: u64, cpu_usage: f32, pub(crate) updated: bool, + pub read_bytes: u64, + pub write_bytes: u64 } unsafe fn get_process_name(process_handler: HANDLE, h_mod: *mut c_void) -> String { @@ -218,6 +225,8 @@ impl Process { old_user_cpu: 0, start_time: unsafe { get_start_time(handle) }, updated: true, + read_bytes: 0, + write_bytes: 0, } } else { Process { @@ -239,6 +248,8 @@ impl Process { old_user_cpu: 0, start_time: 0, updated: true, + read_bytes: 0, + write_bytes: 0 } } } @@ -310,6 +321,8 @@ impl ProcessExt for Process { old_user_cpu: 0, start_time: 0, updated: true, + read_bytes: 0, + write_bytes: 0, } } } @@ -585,6 +598,38 @@ pub(crate) fn get_system_computation_time() -> ULARGE_INTEGER { } } +pub(crate) fn get_disk_usage(p: &mut Process){ + let r = ProcessDiagnosticInfo::try_get_for_process_id(p.pid as u32).ok(); + if r.is_some(){ + let r = r.unwrap(); + if r.is_some(){ + let du = r.unwrap().get_disk_usage().ok(); + if du.is_some(){ + let du = du.unwrap(); + if du.is_some(){ + let report = du.unwrap().get_report().ok(); + if report.is_some(){ + let report = report.unwrap(); + if report.is_some(){ + let report = report.unwrap(); + let read_bytes = report.get_bytes_read_count().ok(); + let write_bytes = report.get_bytes_written_count().ok(); + if read_bytes.is_some(){ + p.read_bytes = read_bytes.unwrap() as u64; + } + if write_bytes.is_some(){ + p.write_bytes = write_bytes.unwrap() as u64; + } + } + } + } + } + + } + + } +} + pub(crate) fn compute_cpu_usage(p: &mut Process, nb_processors: u64, now: ULARGE_INTEGER) { unsafe { let mut sys: ULARGE_INTEGER = ::std::mem::zeroed(); @@ -627,6 +672,7 @@ pub fn get_handle(p: &Process) -> HANDLE { pub fn update_proc_info(p: &mut Process) { update_memory(p); + get_disk_usage(p); } pub fn update_memory(p: &mut Process) { diff --git a/src/windows/system.rs b/src/windows/system.rs index dfa13ccf6..42ceed363 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -23,7 +23,7 @@ use SystemExt; use User; use windows::process::{ - compute_cpu_usage, get_handle, get_system_computation_time, update_proc_info, Process, + compute_cpu_usage, get_handle, get_system_computation_time, update_proc_info, Process, get_disk_usage }; use windows::tools::*; @@ -251,6 +251,7 @@ impl SystemExt for System { proc_.memory = (pi.WorkingSetSize as u64) >> 10u64; proc_.virtual_memory = (pi.VirtualSize as u64) >> 10u64; compute_cpu_usage(proc_, nb_processors, system_time); + get_disk_usage(proc_); proc_.updated = true; return None; } @@ -266,6 +267,7 @@ impl SystemExt for System { (pi.VirtualSize as u64) >> 10u64, name, ); + get_disk_usage(&mut p); compute_cpu_usage(&mut p, nb_processors, system_time); Some(p) }) diff --git a/tests/process.rs b/tests/process.rs index fcabbe6a3..dcee29c93 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -60,3 +60,25 @@ fn test_get_cmd_line() { let process = s.get_process(p.id() as sysinfo::Pid).unwrap(); assert_eq!(process.cmd(), &["sleep", "3"]); } + +#[test] +fn test_process_disk_usage() { + use sysinfo::{ProcessExt, SystemExt}; + use std::fs::File; + use std::fs; + use std::io::prelude::*; + { + let mut file = File::create("test.txt").unwrap(); + file.write_all(b"This is a test file\nwith test data.\n").unwrap(); + } + fs::remove_file("test.txt").ok(); + let mut system = sysinfo::System::new(); + system.refresh_processes(); + let process_list = system.get_process_list(); + let mut write_bytes: u64 = 0; + for p in process_list.values(){ + write_bytes += p.write_bytes; + } + + assert!(write_bytes > 0); +} From c8bded8b0a3d4b9d13e4628aa32790af66087b25 Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Mon, 27 Jan 2020 21:54:28 -0600 Subject: [PATCH 05/28] refactored to more closely match crate style --- src/linux/process.rs | 14 +++++++++++--- src/mac/process.rs | 20 ++++++++++++++------ src/traits.rs | 6 ++++++ src/windows/process.rs | 12 ++++++------ tests/process.rs | 2 +- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/linux/process.rs b/src/linux/process.rs index 11dd8c42b..cfbae6ab6 100644 --- a/src/linux/process.rs +++ b/src/linux/process.rs @@ -124,8 +124,8 @@ pub struct Process { /// Tasks run by this process. pub tasks: HashMap, pub(crate) stat_file: Option, - pub read_bytes: u64, - pub write_bytes: u64 + pub(crate) read_bytes: u64, + pub(crate) written_bytes: u64 } impl ProcessExt for Process { @@ -158,7 +158,7 @@ impl ProcessExt for Process { }, stat_file: None, read_bytes: 0, - write_bytes: 0 + written_bytes: 0 } } @@ -219,6 +219,14 @@ impl ProcessExt for Process { fn cpu_usage(&self) -> f32 { self.cpu_usage } + + fn read_bytes(&self) -> u64{ + self.read_bytes + } + + fn written_bytes(&self) -> u64{ + self.written_bytes + } } impl Drop for Process { diff --git a/src/mac/process.rs b/src/mac/process.rs index ad560c1d0..1b1e2ddc4 100644 --- a/src/mac/process.rs +++ b/src/mac/process.rs @@ -149,8 +149,8 @@ pub struct Process { /// /// This is very likely this one that you want instead of `process_status`. pub status: Option, - pub read_bytes: u64, - pub write_bytes: u64 + pub(crate) read_bytes: u64, + pub(crate) written_bytes: u64 } impl Process { @@ -178,7 +178,7 @@ impl Process { process_status: ProcessStatus::Unknown(0), status: None, read_bytes: 0, - write_bytes: 0 + written_bytes: 0 } } @@ -215,7 +215,7 @@ impl Process { process_status: ProcessStatus::Unknown(0), status: None, read_bytes: 0, - write_bytes: 0 + written_bytes: 0 } } } @@ -245,7 +245,7 @@ impl ProcessExt for Process { process_status: ProcessStatus::Unknown(0), status: None, read_bytes: 0, - write_bytes: 0 + written_bytes: 0 } } @@ -304,6 +304,14 @@ impl ProcessExt for Process { fn cpu_usage(&self) -> f32 { self.cpu_usage } + + fn read_bytes(&self) -> u64{ + self.read_bytes + } + + fn written_bytes(&self) -> u64{ + self.written_bytes + } } pub(crate) fn compute_cpu_usage(p: &mut Process, time: u64, task_time: u64) { @@ -599,7 +607,7 @@ fn update_proc_disk_activity(p: &mut Process){ } else{ p.read_bytes = pidrusage.ri_diskio_bytesread; - p.write_bytes = pidrusage.ri_diskio_byteswritten; + p.written_bytes = pidrusage.ri_diskio_byteswritten; } } diff --git a/src/traits.rs b/src/traits.rs index 88a3122b8..b5c9bcc42 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -295,6 +295,12 @@ pub trait ProcessExt: Debug { /// } /// ``` fn cpu_usage(&self) -> f32; + + /// Returns number of bytes read from disk + fn read_bytes(&self) -> u64; + + /// Returns number of bytes written to disk + fn written_bytes(&self) -> u64; } /// Contains all the methods of the [`Processor`][crate::Processor] struct. diff --git a/src/windows/process.rs b/src/windows/process.rs index e7a4329db..ef8c2196d 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -105,8 +105,8 @@ pub struct Process { start_time: u64, cpu_usage: f32, pub(crate) updated: bool, - pub read_bytes: u64, - pub write_bytes: u64 + pub(crate) read_bytes: u64, + pub(crate) written_bytes: u64 } unsafe fn get_process_name(process_handler: HANDLE, h_mod: *mut c_void) -> String { @@ -226,7 +226,7 @@ impl Process { start_time: unsafe { get_start_time(handle) }, updated: true, read_bytes: 0, - write_bytes: 0, + written_bytes: 0, } } else { Process { @@ -249,7 +249,7 @@ impl Process { start_time: 0, updated: true, read_bytes: 0, - write_bytes: 0 + written_bytes: 0 } } } @@ -322,7 +322,7 @@ impl ProcessExt for Process { start_time: 0, updated: true, read_bytes: 0, - write_bytes: 0, + written_bytes: 0 } } } @@ -618,7 +618,7 @@ pub(crate) fn get_disk_usage(p: &mut Process){ p.read_bytes = read_bytes.unwrap() as u64; } if write_bytes.is_some(){ - p.write_bytes = write_bytes.unwrap() as u64; + p.written_bytes = write_bytes.unwrap() as u64; } } } diff --git a/tests/process.rs b/tests/process.rs index dcee29c93..f7e325c95 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -77,7 +77,7 @@ fn test_process_disk_usage() { let process_list = system.get_process_list(); let mut write_bytes: u64 = 0; for p in process_list.values(){ - write_bytes += p.write_bytes; + write_bytes += p.written_bytes(); } assert!(write_bytes > 0); From 5b684bf8faa9672fecb0af078a1b3c1cfe1da7c0 Mon Sep 17 00:00:00 2001 From: benjamin Date: Mon, 27 Jan 2020 21:58:29 -0600 Subject: [PATCH 06/28] missed one --- src/linux/system.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux/system.rs b/src/linux/system.rs index c515be86d..7d4892cab 100644 --- a/src/linux/system.rs +++ b/src/linux/system.rs @@ -838,7 +838,7 @@ fn update_process_disk_activity(p: &mut Process){ p.read_bytes = d[1].parse::().unwrap_or(0); } else if d[0] == "write_bytes"{ - p.write_bytes = d[1].parse::().unwrap_or(0); + p.written_bytes = d[1].parse::().unwrap_or(0); } } } From f9045133c0e85cd63c44faa51310ae6946421d37 Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Tue, 28 Jan 2020 09:26:13 -0600 Subject: [PATCH 07/28] added read_bytes/written_bytes to complete trait for windows --- src/windows/process.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/windows/process.rs b/src/windows/process.rs index ef8c2196d..d98a2bffa 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -387,6 +387,14 @@ impl ProcessExt for Process { fn cpu_usage(&self) -> f32 { self.cpu_usage } + + fn read_bytes(&self) -> u64{ + self.read_bytes + } + + fn written_bytes(&self) -> u64{ + self.written_bytes + } } impl Drop for Process { From 49eacdae433c184d419866f44c03a90aa8d29e2e Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Tue, 28 Jan 2020 22:04:57 -0600 Subject: [PATCH 08/28] Changed test to check only current pid --- tests/process.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/process.rs b/tests/process.rs index f7e325c95..47629c9dc 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -63,7 +63,7 @@ fn test_get_cmd_line() { #[test] fn test_process_disk_usage() { - use sysinfo::{ProcessExt, SystemExt}; + use sysinfo::{ProcessExt, SystemExt, get_current_pid}; use std::fs::File; use std::fs; use std::io::prelude::*; @@ -72,13 +72,8 @@ fn test_process_disk_usage() { file.write_all(b"This is a test file\nwith test data.\n").unwrap(); } fs::remove_file("test.txt").ok(); - let mut system = sysinfo::System::new(); - system.refresh_processes(); - let process_list = system.get_process_list(); - let mut write_bytes: u64 = 0; - for p in process_list.values(){ - write_bytes += p.written_bytes(); - } + let system = sysinfo::System::new(); + let p = system.get_process(get_current_pid().expect("Failed retrieving current pid.")).expect("failed to get process"); - assert!(write_bytes > 0); + assert!(p.written_bytes() > 0); } From 09a36fe2de6f54be6a4de43aeb47a2b3c8808171 Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Wed, 29 Jan 2020 23:30:04 -0600 Subject: [PATCH 09/28] refactored to remove usage of unwrap --- src/windows/process.rs | 60 ++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/windows/process.rs b/src/windows/process.rs index d98a2bffa..412cdb887 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -607,35 +607,37 @@ pub(crate) fn get_system_computation_time() -> ULARGE_INTEGER { } pub(crate) fn get_disk_usage(p: &mut Process){ - let r = ProcessDiagnosticInfo::try_get_for_process_id(p.pid as u32).ok(); - if r.is_some(){ - let r = r.unwrap(); - if r.is_some(){ - let du = r.unwrap().get_disk_usage().ok(); - if du.is_some(){ - let du = du.unwrap(); - if du.is_some(){ - let report = du.unwrap().get_report().ok(); - if report.is_some(){ - let report = report.unwrap(); - if report.is_some(){ - let report = report.unwrap(); - let read_bytes = report.get_bytes_read_count().ok(); - let write_bytes = report.get_bytes_written_count().ok(); - if read_bytes.is_some(){ - p.read_bytes = read_bytes.unwrap() as u64; - } - if write_bytes.is_some(){ - p.written_bytes = write_bytes.unwrap() as u64; - } - } - } - } - } - - } - - } + let diag_info = ProcessDiagnosticInfo::try_get_for_process_id(p.pid as u32).ok(); + match diag_info{ + Some(diag_info) => match diag_info{ + Some(diag_info) => match diag_info.get_disk_usage().ok(){ + Some(disk_usage) => match disk_usage{ + Some(disk_usage) => match disk_usage.get_report().ok(){ + Some(report) => match report{ + Some(report) => { + let read_bytes = report.get_bytes_read_count().ok(); + let write_bytes = report.get_bytes_written_count().ok(); + match read_bytes{ + Some(read_bytes) => p.read_bytes = read_bytes as u64, + None => {} + }; + match write_bytes{ + Some(write_bytes) => p.written_bytes = write_bytes as u64, + None => {} + }; + }, + None => {} + }, + None => {} + }, + None => {} + }, + None => {} + }, + None => {} + }, + None => {} + }; } pub(crate) fn compute_cpu_usage(p: &mut Process, nb_processors: u64, now: ULARGE_INTEGER) { From a5f28215aef3a78b37a9a0a941abbbdc430a3cad Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Wed, 29 Jan 2020 23:34:29 -0600 Subject: [PATCH 10/28] cargo fmt --- src/linux/process.rs | 8 ++++---- src/linux/system.rs | 13 ++++++------- src/mac/ffi.rs | 36 ++++++++++++++++++------------------ src/mac/process.rs | 21 ++++++++++----------- src/windows/process.rs | 32 ++++++++++++++++---------------- src/windows/system.rs | 3 ++- tests/process.rs | 9 +++++++-- 7 files changed, 63 insertions(+), 59 deletions(-) diff --git a/src/linux/process.rs b/src/linux/process.rs index cfbae6ab6..4840cc078 100644 --- a/src/linux/process.rs +++ b/src/linux/process.rs @@ -125,7 +125,7 @@ pub struct Process { pub tasks: HashMap, pub(crate) stat_file: Option, pub(crate) read_bytes: u64, - pub(crate) written_bytes: u64 + pub(crate) written_bytes: u64, } impl ProcessExt for Process { @@ -158,7 +158,7 @@ impl ProcessExt for Process { }, stat_file: None, read_bytes: 0, - written_bytes: 0 + written_bytes: 0, } } @@ -220,11 +220,11 @@ impl ProcessExt for Process { self.cpu_usage } - fn read_bytes(&self) -> u64{ + fn read_bytes(&self) -> u64 { self.read_bytes } - fn written_bytes(&self) -> u64{ + fn written_bytes(&self) -> u64 { self.written_bytes } } diff --git a/src/linux/system.rs b/src/linux/system.rs index 7d4892cab..2b5e435d8 100644 --- a/src/linux/system.rs +++ b/src/linux/system.rs @@ -826,18 +826,17 @@ fn _get_process_data( Ok(Some(p)) } -fn update_process_disk_activity(p: &mut Process){ +fn update_process_disk_activity(p: &mut Process) { let path = PathBuf::from(format!("/proc/{}/io", p.pid)); - let data = match get_all_data(&path, 16_384){ + let data = match get_all_data(&path, 16_384) { Ok(d) => d, - Err(_) => return + Err(_) => return, }; let data: Vec> = data.split("\n").map(|l| l.split(": ").collect()).collect(); - for d in data.iter(){ - if d[0] == "read_bytes"{ + for d in data.iter() { + if d[0] == "read_bytes" { p.read_bytes = d[1].parse::().unwrap_or(0); - } - else if d[0] == "write_bytes"{ + } else if d[0] == "write_bytes" { p.written_bytes = d[1].parse::().unwrap_or(0); } } diff --git a/src/mac/ffi.rs b/src/mac/ffi.rs index 236788b93..97fd3d555 100644 --- a/src/mac/ffi.rs +++ b/src/mac/ffi.rs @@ -131,7 +131,7 @@ extern "C" { } #[link(name = "proc", kind = "dylib")] -extern { +extern "C" { pub fn proc_pid_rusage(pid: c_int, flavor: c_int, buffer: *mut c_void) -> c_int; } @@ -440,25 +440,25 @@ pub struct xsw_usage { #[repr(C)] #[derive(Debug, Default)] pub struct RUsageInfoV2 { - pub ri_uuid : [u8; 16], - pub ri_user_time : u64, - pub ri_system_time : u64, - pub ri_pkg_idle_wkups : u64, - pub ri_interrupt_wkups : u64, - pub ri_pageins : u64, - pub ri_wired_size : u64, - pub ri_resident_size : u64, - pub ri_phys_footprint : u64, - pub ri_proc_start_abstime : u64, - pub ri_proc_exit_abstime : u64, - pub ri_child_user_time : u64, - pub ri_child_system_time : u64, - pub ri_child_pkg_idle_wkups : u64, + pub ri_uuid: [u8; 16], + pub ri_user_time: u64, + pub ri_system_time: u64, + pub ri_pkg_idle_wkups: u64, + pub ri_interrupt_wkups: u64, + pub ri_pageins: u64, + pub ri_wired_size: u64, + pub ri_resident_size: u64, + pub ri_phys_footprint: u64, + pub ri_proc_start_abstime: u64, + pub ri_proc_exit_abstime: u64, + pub ri_child_user_time: u64, + pub ri_child_system_time: u64, + pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, - pub ri_child_pageins : u64, + pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, - pub ri_diskio_bytesread : u64, - pub ri_diskio_byteswritten : u64, + pub ri_diskio_bytesread: u64, + pub ri_diskio_byteswritten: u64, } //pub const HOST_CPU_LOAD_INFO_COUNT: usize = 4; diff --git a/src/mac/process.rs b/src/mac/process.rs index 1b1e2ddc4..c23ed8726 100644 --- a/src/mac/process.rs +++ b/src/mac/process.rs @@ -150,7 +150,7 @@ pub struct Process { /// This is very likely this one that you want instead of `process_status`. pub status: Option, pub(crate) read_bytes: u64, - pub(crate) written_bytes: u64 + pub(crate) written_bytes: u64, } impl Process { @@ -178,7 +178,7 @@ impl Process { process_status: ProcessStatus::Unknown(0), status: None, read_bytes: 0, - written_bytes: 0 + written_bytes: 0, } } @@ -215,7 +215,7 @@ impl Process { process_status: ProcessStatus::Unknown(0), status: None, read_bytes: 0, - written_bytes: 0 + written_bytes: 0, } } } @@ -245,7 +245,7 @@ impl ProcessExt for Process { process_status: ProcessStatus::Unknown(0), status: None, read_bytes: 0, - written_bytes: 0 + written_bytes: 0, } } @@ -305,11 +305,11 @@ impl ProcessExt for Process { self.cpu_usage } - fn read_bytes(&self) -> u64{ + fn read_bytes(&self) -> u64 { self.read_bytes } - fn written_bytes(&self) -> u64{ + fn written_bytes(&self) -> u64 { self.written_bytes } } @@ -594,18 +594,17 @@ pub(crate) fn update_process( } } -fn update_proc_disk_activity(p: &mut Process){ +fn update_proc_disk_activity(p: &mut Process) { let mut pidrusage = ffi::RUsageInfoV2::default(); let ptr = &mut pidrusage as *mut _ as *mut c_void; let retval: i32; - unsafe{ + unsafe { retval = ffi::proc_pid_rusage(p.pid() as c_int, 2, ptr); } - if retval < 0{ + if retval < 0 { panic!("proc_pid_rusage failed: {:?}", retval); - } - else{ + } else { p.read_bytes = pidrusage.ri_diskio_bytesread; p.written_bytes = pidrusage.ri_diskio_byteswritten; } diff --git a/src/windows/process.rs b/src/windows/process.rs index 412cdb887..b9193703f 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -32,8 +32,8 @@ use winapi::um::winnt::{ HANDLE, /*, PWSTR*/ PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ, ULARGE_INTEGER, /*THREAD_GET_CONTEXT, THREAD_QUERY_INFORMATION, THREAD_SUSPEND_RESUME,*/ }; -use winrt::*; use winrt::windows::system::diagnostics::*; +use winrt::*; /// Enum describing the different status of a process. #[derive(Clone, Copy, Debug)] @@ -106,7 +106,7 @@ pub struct Process { cpu_usage: f32, pub(crate) updated: bool, pub(crate) read_bytes: u64, - pub(crate) written_bytes: u64 + pub(crate) written_bytes: u64, } unsafe fn get_process_name(process_handler: HANDLE, h_mod: *mut c_void) -> String { @@ -249,7 +249,7 @@ impl Process { start_time: 0, updated: true, read_bytes: 0, - written_bytes: 0 + written_bytes: 0, } } } @@ -322,7 +322,7 @@ impl ProcessExt for Process { start_time: 0, updated: true, read_bytes: 0, - written_bytes: 0 + written_bytes: 0, } } } @@ -388,11 +388,11 @@ impl ProcessExt for Process { self.cpu_usage } - fn read_bytes(&self) -> u64{ + fn read_bytes(&self) -> u64 { self.read_bytes } - fn written_bytes(&self) -> u64{ + fn written_bytes(&self) -> u64 { self.written_bytes } } @@ -606,26 +606,26 @@ pub(crate) fn get_system_computation_time() -> ULARGE_INTEGER { } } -pub(crate) fn get_disk_usage(p: &mut Process){ +pub(crate) fn get_disk_usage(p: &mut Process) { let diag_info = ProcessDiagnosticInfo::try_get_for_process_id(p.pid as u32).ok(); - match diag_info{ - Some(diag_info) => match diag_info{ - Some(diag_info) => match diag_info.get_disk_usage().ok(){ - Some(disk_usage) => match disk_usage{ - Some(disk_usage) => match disk_usage.get_report().ok(){ - Some(report) => match report{ + match diag_info { + Some(diag_info) => match diag_info { + Some(diag_info) => match diag_info.get_disk_usage().ok() { + Some(disk_usage) => match disk_usage { + Some(disk_usage) => match disk_usage.get_report().ok() { + Some(report) => match report { Some(report) => { let read_bytes = report.get_bytes_read_count().ok(); let write_bytes = report.get_bytes_written_count().ok(); - match read_bytes{ + match read_bytes { Some(read_bytes) => p.read_bytes = read_bytes as u64, None => {} }; - match write_bytes{ + match write_bytes { Some(write_bytes) => p.written_bytes = write_bytes as u64, None => {} }; - }, + } None => {} }, None => {} diff --git a/src/windows/system.rs b/src/windows/system.rs index 42ceed363..dc4b4b83f 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -23,7 +23,8 @@ use SystemExt; use User; use windows::process::{ - compute_cpu_usage, get_handle, get_system_computation_time, update_proc_info, Process, get_disk_usage + compute_cpu_usage, get_disk_usage, get_handle, get_system_computation_time, update_proc_info, + Process, }; use windows::tools::*; diff --git a/tests/process.rs b/tests/process.rs index 47629c9dc..c8b0b013f 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -66,14 +66,19 @@ fn test_process_disk_usage() { use sysinfo::{ProcessExt, SystemExt, get_current_pid}; use std::fs::File; use std::fs; + use std::fs::File; use std::io::prelude::*; + use sysinfo::{get_current_pid, ProcessExt, SystemExt}; { let mut file = File::create("test.txt").unwrap(); - file.write_all(b"This is a test file\nwith test data.\n").unwrap(); + file.write_all(b"This is a test file\nwith test data.\n") + .unwrap(); } fs::remove_file("test.txt").ok(); let system = sysinfo::System::new(); - let p = system.get_process(get_current_pid().expect("Failed retrieving current pid.")).expect("failed to get process"); + let p = system + .get_process(get_current_pid().expect("Failed retrieving current pid.")) + .expect("failed to get process"); assert!(p.written_bytes() > 0); } From de696d9e450d21b9f3078aa1cd345405502d848e Mon Sep 17 00:00:00 2001 From: Benjamin Vaisvil Date: Thu, 30 Jan 2020 22:26:59 -0600 Subject: [PATCH 11/28] cleaned up get_disk_usage --- src/windows/process.rs | 61 +++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/windows/process.rs b/src/windows/process.rs index b9193703f..f6a5aa789 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -606,40 +606,39 @@ pub(crate) fn get_system_computation_time() -> ULARGE_INTEGER { } } -pub(crate) fn get_disk_usage(p: &mut Process) { - let diag_info = ProcessDiagnosticInfo::try_get_for_process_id(p.pid as u32).ok(); - match diag_info { - Some(diag_info) => match diag_info { - Some(diag_info) => match diag_info.get_disk_usage().ok() { - Some(disk_usage) => match disk_usage { - Some(disk_usage) => match disk_usage.get_report().ok() { - Some(report) => match report { - Some(report) => { - let read_bytes = report.get_bytes_read_count().ok(); - let write_bytes = report.get_bytes_written_count().ok(); - match read_bytes { - Some(read_bytes) => p.read_bytes = read_bytes as u64, - None => {} - }; - match write_bytes { - Some(write_bytes) => p.written_bytes = write_bytes as u64, - None => {} - }; - } - None => {} - }, - None => {} - }, - None => {} - }, - None => {} - }, - None => {} - }, - None => {} +macro_rules! safe_unwrap { + ($x:expr) => { + match $x { + Some(x) => x, + None => return, + } + }; +} + +macro_rules! safe_unwrap_to_inner { + ($x:expr) => { + match $x { + Some(x) => safe_unwrap!(x), + None => return, + } }; } +pub(crate) fn get_disk_usage(p: &mut Process) { + let diag_info = + safe_unwrap_to_inner!(ProcessDiagnosticInfo::try_get_for_process_id(p.pid as u32).ok()); + let disk_usage = safe_unwrap_to_inner!(diag_info.get_disk_usage().ok()); + let report = safe_unwrap_to_inner!(disk_usage.get_report().ok()); + let read_bytes = report.get_bytes_read_count().ok(); + let write_bytes = report.get_bytes_written_count().ok(); + if let Some(rb) = read_bytes { + p.read_bytes = rb as u64; + } + if let Some(wb) = write_bytes { + p.written_bytes = wb as u64; + } +} + pub(crate) fn compute_cpu_usage(p: &mut Process, nb_processors: u64, now: ULARGE_INTEGER) { unsafe { let mut sys: ULARGE_INTEGER = ::std::mem::zeroed(); From b1f8e4f136f4b39a7c2d8bc3b0f629d60a6ac4bb Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Sun, 5 Apr 2020 12:47:42 +0200 Subject: [PATCH 12/28] Improve Windows situation for disk usage --- src/windows/process.rs | 77 ++++++++++++++++++++++++++---------------- src/windows/system.rs | 26 +++++++++++++- 2 files changed, 73 insertions(+), 30 deletions(-) diff --git a/src/windows/process.rs b/src/windows/process.rs index f6a5aa789..2f3aa8519 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -28,12 +28,9 @@ use winapi::um::psapi::{ LIST_MODULES_ALL, PROCESS_MEMORY_COUNTERS, PROCESS_MEMORY_COUNTERS_EX, }; use winapi::um::sysinfoapi::GetSystemTimeAsFileTime; -use winapi::um::winnt::{ - HANDLE, /*, PWSTR*/ PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE, PROCESS_VM_READ, - ULARGE_INTEGER, /*THREAD_GET_CONTEXT, THREAD_QUERY_INFORMATION, THREAD_SUSPEND_RESUME,*/ -}; -use winrt::windows::system::diagnostics::*; -use winrt::*; +use winapi::um::winnt::{HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ, ULARGE_INTEGER}; +use winrt::windows::system::diagnostics::{ProcessDiagnosticInfo}; +use winrt::ComPtr; /// Enum describing the different status of a process. #[derive(Clone, Copy, Debug)] @@ -71,21 +68,20 @@ fn get_process_handler(pid: Pid) -> Option { } #[derive(Clone)] -struct HandleWrapper(HANDLE); +struct PtrWrapper(T); -impl Deref for HandleWrapper { - type Target = HANDLE; +impl Deref for PtrWrapper { + type Target = T; - fn deref(&self) -> &HANDLE { + fn deref(&self) -> &Self::Target { &self.0 } } -unsafe impl Send for HandleWrapper {} -unsafe impl Sync for HandleWrapper {} +unsafe impl Send for PtrWrapper {} +unsafe impl Sync for PtrWrapper {} /// Struct containing a process' information. -#[derive(Clone)] pub struct Process { name: String, cmd: Vec, @@ -98,7 +94,7 @@ pub struct Process { pub(crate) virtual_memory: u64, parent: Option, status: ProcessStatus, - handle: HandleWrapper, + handle: PtrWrapper, old_cpu: u64, old_sys_cpu: u64, old_user_cpu: u64, @@ -107,6 +103,7 @@ pub struct Process { pub(crate) updated: bool, pub(crate) read_bytes: u64, pub(crate) written_bytes: u64, + diag_info: Option>>, } unsafe fn get_process_name(process_handler: HANDLE, h_mod: *mut c_void) -> String { @@ -207,7 +204,7 @@ impl Process { let mut root = exe.clone(); root.pop(); Process { - handle: HandleWrapper(handle), + handle: PtrWrapper(handle), name, pid, parent, @@ -227,10 +224,15 @@ impl Process { updated: true, read_bytes: 0, written_bytes: 0, + diag_info: + ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) + .ok() + .and_then(|x| x) + .map(|x| PtrWrapper(x)) } } else { Process { - handle: HandleWrapper(null_mut()), + handle: PtrWrapper(null_mut()), name, pid, parent, @@ -250,6 +252,11 @@ impl Process { updated: true, read_bytes: 0, written_bytes: 0, + diag_info: + ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) + .ok() + .and_then(|x| x) + .map(|x| PtrWrapper(x)) } } } @@ -269,7 +276,7 @@ impl Process { let mut root = exe.clone(); root.pop(); Process { - handle: HandleWrapper(process_handler), + handle: PtrWrapper(process_handler), name, pid, parent, @@ -287,6 +294,13 @@ impl Process { old_user_cpu: 0, start_time: get_start_time(process_handler), updated: true, + read_bytes: 0, + written_bytes: 0, + diag_info: + ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) + .ok() + .and_then(|x| x) + .map(|x| PtrWrapper(x)) } } } @@ -303,7 +317,7 @@ impl ProcessExt for Process { Process::new_with_handle(pid, parent, process_handler) } else { Process { - handle: HandleWrapper(null_mut()), + handle: PtrWrapper(null_mut()), name: String::new(), pid, parent, @@ -323,6 +337,11 @@ impl ProcessExt for Process { updated: true, read_bytes: 0, written_bytes: 0, + diag_info: + ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) + .ok() + .and_then(|x| x) + .map(|x| PtrWrapper(x)) } } } @@ -625,17 +644,17 @@ macro_rules! safe_unwrap_to_inner { } pub(crate) fn get_disk_usage(p: &mut Process) { - let diag_info = - safe_unwrap_to_inner!(ProcessDiagnosticInfo::try_get_for_process_id(p.pid as u32).ok()); - let disk_usage = safe_unwrap_to_inner!(diag_info.get_disk_usage().ok()); - let report = safe_unwrap_to_inner!(disk_usage.get_report().ok()); - let read_bytes = report.get_bytes_read_count().ok(); - let write_bytes = report.get_bytes_written_count().ok(); - if let Some(rb) = read_bytes { - p.read_bytes = rb as u64; - } - if let Some(wb) = write_bytes { - p.written_bytes = wb as u64; + if let Some(ref diag_info) = p.diag_info { + let disk_usage = safe_unwrap_to_inner!(diag_info.get_disk_usage().ok()); + let report = safe_unwrap_to_inner!(disk_usage.get_report().ok()); + let read_bytes = report.get_bytes_read_count().ok(); + let write_bytes = report.get_bytes_written_count().ok(); + if let Some(rb) = read_bytes { + p.read_bytes = rb as u64; + } + if let Some(wb) = write_bytes { + p.written_bytes = wb as u64; + } } } diff --git a/src/windows/system.rs b/src/windows/system.rs index dc4b4b83f..d03eb3a19 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -38,8 +38,9 @@ use winapi::um::minwinbase::STILL_ACTIVE; use winapi::um::processthreadsapi::GetExitCodeProcess; use winapi::um::sysinfoapi::{GetTickCount64, GlobalMemoryStatusEx, MEMORYSTATUSEX}; use winapi::um::winnt::HANDLE; - use rayon::prelude::*; +use winrt::windows::system::{AppDiagnosticInfo, DiagnosticAccessStatus}; +use winrt::{RtAsyncOperation}; /// Struct containing the system's information. pub struct System { @@ -77,9 +78,32 @@ unsafe fn boot_time() -> u64 { } } +#[cfg(feature = "debug")] +macro_rules! sysinfo_debug { + ($($x:tt)*) => {{ + eprintln!($($x)*); + }} +} + +#[cfg(not(feature = "debug"))] +macro_rules! sysinfo_debug { + ($($x:tt)*) => {{}} +} + impl SystemExt for System { #[allow(non_snake_case)] fn new_with_specifics(refreshes: RefreshKind) -> System { + match AppDiagnosticInfo::request_access_async() { + Ok(x) => { + match x.blocking_get() { + Ok(DiagnosticAccessStatus::Unspecified) => sysinfo_debug!("app diagnostic access refused: Unspecified"), + Ok(DiagnosticAccessStatus::Denied) => sysinfo_debug!("app diagnostic access refused: Denied"), + Ok(_) => {} + Err(_e) => sysinfo_debug!("failed to get access request status: {:?}", _e), + } + } + Err(_e) => sysinfo_debug!("failed to request app diagnostic access: {:?}", _e), + } let (processors, vendor_id, brand) = init_processors(); let mut s = System { process_list: HashMap::with_capacity(500), From 8005a36810beaf5427907008e12472354290da07 Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Sun, 5 Apr 2020 13:35:37 +0200 Subject: [PATCH 13/28] Move common types to common file --- src/common.rs | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ src/sysinfo.rs | 127 +------------------------------------------------ 2 files changed, 127 insertions(+), 126 deletions(-) diff --git a/src/common.rs b/src/common.rs index 632debad5..e9696cea4 100644 --- a/src/common.rs +++ b/src/common.rs @@ -7,6 +7,7 @@ use NetworkData; use Networks; use NetworksExt; +use UserExt; /// Trait to have a common fallback for the [`Pid`][crate::Pid] type. pub trait AsU32 { @@ -273,3 +274,128 @@ impl From for DiskType { } } } + +/// An enum representing signal on UNIX-like systems. +#[repr(C)] +#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] +pub enum Signal { + /// Hangup detected on controlling terminal or death of controlling process. + Hangup = 1, + /// Interrupt from keyboard. + Interrupt = 2, + /// Quit from keyboard. + Quit = 3, + /// Illegal instruction. + Illegal = 4, + /// Trace/breakpoint trap. + Trap = 5, + /// Abort signal from C abort function. + Abort = 6, + // IOT trap. A synonym for SIGABRT. + // IOT = 6, + /// Bus error (bad memory access). + Bus = 7, + /// Floating point exception. + FloatingPointException = 8, + /// Kill signal. + Kill = 9, + /// User-defined signal 1. + User1 = 10, + /// Invalid memory reference. + Segv = 11, + /// User-defined signal 2. + User2 = 12, + /// Broken pipe: write to pipe with no readers. + Pipe = 13, + /// Timer signal from C alarm function. + Alarm = 14, + /// Termination signal. + Term = 15, + /// Stack fault on coprocessor (unused). + Stklft = 16, + /// Child stopped or terminated. + Child = 17, + /// Continue if stopped. + Continue = 18, + /// Stop process. + Stop = 19, + /// Stop typed at terminal. + TSTP = 20, + /// Terminal input for background process. + TTIN = 21, + /// Terminal output for background process. + TTOU = 22, + /// Urgent condition on socket. + Urgent = 23, + /// CPU time limit exceeded. + XCPU = 24, + /// File size limit exceeded. + XFSZ = 25, + /// Virtual alarm clock. + VirtualAlarm = 26, + /// Profiling time expired. + Profiling = 27, + /// Windows resize signal. + Winch = 28, + /// I/O now possible. + IO = 29, + // Pollable event (Sys V). Synonym for IO + //Poll = 29, + /// Power failure (System V). + Power = 30, + /// Bad argument to routine (SVr4). + Sys = 31, +} + +/// A struct representing system load average value. +/// +/// It is returned by [`SystemExt::get_load_average`]. +/// +/// ```no_run +/// use sysinfo::{System, SystemExt}; +/// +/// let s = System::new_all(); +/// let load_avg = s.get_load_average(); +/// println!( +/// "one minute: {}%, five minutes: {}%, fifteen minutes: {}%", +/// load_avg.one, +/// load_avg.five, +/// load_avg.fifteen, +/// ); +/// ``` +#[repr(C)] +#[derive(Default, Debug, Clone)] +pub struct LoadAvg { + /// Average load within one minute. + pub one: f64, + /// Average load within five minutes. + pub five: f64, + /// Average load within fifteen minutes. + pub fifteen: f64, +} + +/// Type containing user information. +/// +/// It is returned by [`SystemExt::get_users`]. +/// +/// ```no_run +/// use sysinfo::{System, SystemExt}; +/// +/// let s = System::new_all(); +/// println!("users: {:?}", s.get_users()); +/// ``` +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] +pub struct User { + name: String, + groups: Vec, +} + +impl UserExt for User { + fn get_name(&self) -> &str { + &self.name + } + + fn get_groups(&self) -> &[String] { + &self.groups + } +} diff --git a/src/sysinfo.rs b/src/sysinfo.rs index 409fe489b..3e1d65125 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -92,7 +92,7 @@ cfg_if! { } } -pub use common::{AsU32, DiskType, NetworksIter, Pid, RefreshKind}; +pub use common::{AsU32, DiskType, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, User}; pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System}; pub use traits::{ ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt, @@ -159,131 +159,6 @@ pub fn set_open_files_limit(mut _new_limit: isize) -> bool { } } -/// An enum representing signal on UNIX-like systems. -#[repr(C)] -#[derive(Clone, PartialEq, PartialOrd, Debug, Copy)] -pub enum Signal { - /// Hangup detected on controlling terminal or death of controlling process. - Hangup = 1, - /// Interrupt from keyboard. - Interrupt = 2, - /// Quit from keyboard. - Quit = 3, - /// Illegal instruction. - Illegal = 4, - /// Trace/breakpoint trap. - Trap = 5, - /// Abort signal from C abort function. - Abort = 6, - // IOT trap. A synonym for SIGABRT. - // IOT = 6, - /// Bus error (bad memory access). - Bus = 7, - /// Floating point exception. - FloatingPointException = 8, - /// Kill signal. - Kill = 9, - /// User-defined signal 1. - User1 = 10, - /// Invalid memory reference. - Segv = 11, - /// User-defined signal 2. - User2 = 12, - /// Broken pipe: write to pipe with no readers. - Pipe = 13, - /// Timer signal from C alarm function. - Alarm = 14, - /// Termination signal. - Term = 15, - /// Stack fault on coprocessor (unused). - Stklft = 16, - /// Child stopped or terminated. - Child = 17, - /// Continue if stopped. - Continue = 18, - /// Stop process. - Stop = 19, - /// Stop typed at terminal. - TSTP = 20, - /// Terminal input for background process. - TTIN = 21, - /// Terminal output for background process. - TTOU = 22, - /// Urgent condition on socket. - Urgent = 23, - /// CPU time limit exceeded. - XCPU = 24, - /// File size limit exceeded. - XFSZ = 25, - /// Virtual alarm clock. - VirtualAlarm = 26, - /// Profiling time expired. - Profiling = 27, - /// Windows resize signal. - Winch = 28, - /// I/O now possible. - IO = 29, - // Pollable event (Sys V). Synonym for IO - //Poll = 29, - /// Power failure (System V). - Power = 30, - /// Bad argument to routine (SVr4). - Sys = 31, -} - -/// A struct representing system load average value. -/// -/// It is returned by [`SystemExt::get_load_average`]. -/// -/// ```no_run -/// use sysinfo::{System, SystemExt}; -/// -/// let s = System::new_all(); -/// let load_avg = s.get_load_average(); -/// println!( -/// "one minute: {}%, five minutes: {}%, fifteen minutes: {}%", -/// load_avg.one, -/// load_avg.five, -/// load_avg.fifteen, -/// ); -/// ``` -#[repr(C)] -#[derive(Default, Debug, Clone)] -pub struct LoadAvg { - /// Average load within one minute. - pub one: f64, - /// Average load within five minutes. - pub five: f64, - /// Average load within fifteen minutes. - pub fifteen: f64, -} - -/// Type containing user information. -/// -/// It is returned by [`SystemExt::get_users`]. -/// -/// ```no_run -/// use sysinfo::{System, SystemExt}; -/// -/// let s = System::new_all(); -/// println!("users: {:?}", s.get_users()); -/// ``` -#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct User { - name: String, - groups: Vec, -} - -impl UserExt for User { - fn get_name(&self) -> &str { - &self.name - } - - fn get_groups(&self) -> &[String] { - &self.groups - } -} - #[cfg(test)] mod test { use super::*; From b852d547bd4a601534caafebfcbf2ca0222b1113 Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Sun, 5 Apr 2020 13:58:37 +0200 Subject: [PATCH 14/28] Only compute disk usage when required --- src/common.rs | 29 +++++++++++++++-- src/sysinfo.rs | 2 +- src/traits.rs | 21 ++++++++++--- src/windows/process.rs | 70 ++++++++++++------------------------------ src/windows/system.rs | 26 ++++++---------- 5 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/common.rs b/src/common.rs index e9696cea4..80832e839 100644 --- a/src/common.rs +++ b/src/common.rs @@ -386,8 +386,8 @@ pub struct LoadAvg { /// ``` #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct User { - name: String, - groups: Vec, + pub(crate) name: String, + pub(crate) groups: Vec, } impl UserExt for User { @@ -399,3 +399,28 @@ impl UserExt for User { &self.groups } } + +/// Type containing read and written bytes. +/// +/// It is returned by [`ProcessExt::get_disk_usage`]. +/// +/// ```no_run +/// use sysinfo::{ProcessExt, System, SystemExt}; +/// +/// let s = System::new_all(); +/// for (pid, process) in s.get_processes() { +/// let disk_usage = process.get_disk_usage(); +/// println!("[{}] read/written bytes: {}/{}", +/// pid, +/// disk_usage.read_bytes, +/// disk_usage.written_bytes, +/// ); +/// } +/// ``` +#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] +pub struct DiskUsage { + /// Number of written bytes. + pub written_bytes: u64, + /// Number of read bytes. + pub read_bytes: u64, +} diff --git a/src/sysinfo.rs b/src/sysinfo.rs index 3e1d65125..3c55df04f 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -92,7 +92,7 @@ cfg_if! { } } -pub use common::{AsU32, DiskType, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, User}; +pub use common::{AsU32, DiskType, DiskUsage, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, User}; pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System}; pub use traits::{ ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt, diff --git a/src/traits.rs b/src/traits.rs index b5c9bcc42..1f5ee7347 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -6,6 +6,7 @@ use sys::{Component, Disk, Networks, Process, Processor}; use DiskType; +use DiskUsage; use LoadAvg; use NetworksIter; use Pid; @@ -296,11 +297,21 @@ pub trait ProcessExt: Debug { /// ``` fn cpu_usage(&self) -> f32; - /// Returns number of bytes read from disk - fn read_bytes(&self) -> u64; - - /// Returns number of bytes written to disk - fn written_bytes(&self) -> u64; + /// Returns number of bytes read and written to disk. + /// + /// ```no_run + /// use sysinfo::{ProcessExt, System, SystemExt}; + /// + /// let s = System::new(); + /// if let Some(process) = s.get_process(1337) { + /// let disk_usage = process.get_disk_usage(); + /// println!("read/written bytes: {}/{}", + /// disk_usage.read_bytes, + /// disk_usage.written_bytes, + /// ); + /// } + /// ``` + fn get_disk_usage(&self) -> DiskUsage; } /// Contains all the methods of the [`Processor`][crate::Processor] struct. diff --git a/src/windows/process.rs b/src/windows/process.rs index 2f3aa8519..ca571df40 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -14,6 +14,7 @@ use std::str; use libc::{c_void, memcpy}; +use DiskUsage; use Pid; use ProcessExt; @@ -101,8 +102,6 @@ pub struct Process { start_time: u64, cpu_usage: f32, pub(crate) updated: bool, - pub(crate) read_bytes: u64, - pub(crate) written_bytes: u64, diag_info: Option>>, } @@ -222,8 +221,6 @@ impl Process { old_user_cpu: 0, start_time: unsafe { get_start_time(handle) }, updated: true, - read_bytes: 0, - written_bytes: 0, diag_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() @@ -250,8 +247,6 @@ impl Process { old_user_cpu: 0, start_time: 0, updated: true, - read_bytes: 0, - written_bytes: 0, diag_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() @@ -294,8 +289,6 @@ impl Process { old_user_cpu: 0, start_time: get_start_time(process_handler), updated: true, - read_bytes: 0, - written_bytes: 0, diag_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() @@ -335,8 +328,6 @@ impl ProcessExt for Process { old_user_cpu: 0, start_time: 0, updated: true, - read_bytes: 0, - written_bytes: 0, diag_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() @@ -407,12 +398,25 @@ impl ProcessExt for Process { self.cpu_usage } - fn read_bytes(&self) -> u64 { - self.read_bytes - } - - fn written_bytes(&self) -> u64 { - self.written_bytes + fn get_disk_usage(&self) -> DiskUsage { + if let Some(ref diag_info) = self.diag_info { + let disk_usage = match diag_info.get_disk_usage().ok() { + Some(Some(d)) => d, + _ => return DiskUsage::default(), + }; + let report = match disk_usage.get_report().ok() { + Some(Some(d)) => d, + _ => return DiskUsage::default(), + }; + let read_bytes = report.get_bytes_read_count().ok().map(|x| x as u64); + let written_bytes = report.get_bytes_written_count().ok().map(|x| x as u64); + DiskUsage { + read_bytes: read_bytes.unwrap_or(0), + written_bytes: written_bytes.unwrap_or(0), + } + } else { + DiskUsage::default() + } } } @@ -625,39 +629,6 @@ pub(crate) fn get_system_computation_time() -> ULARGE_INTEGER { } } -macro_rules! safe_unwrap { - ($x:expr) => { - match $x { - Some(x) => x, - None => return, - } - }; -} - -macro_rules! safe_unwrap_to_inner { - ($x:expr) => { - match $x { - Some(x) => safe_unwrap!(x), - None => return, - } - }; -} - -pub(crate) fn get_disk_usage(p: &mut Process) { - if let Some(ref diag_info) = p.diag_info { - let disk_usage = safe_unwrap_to_inner!(diag_info.get_disk_usage().ok()); - let report = safe_unwrap_to_inner!(disk_usage.get_report().ok()); - let read_bytes = report.get_bytes_read_count().ok(); - let write_bytes = report.get_bytes_written_count().ok(); - if let Some(rb) = read_bytes { - p.read_bytes = rb as u64; - } - if let Some(wb) = write_bytes { - p.written_bytes = wb as u64; - } - } -} - pub(crate) fn compute_cpu_usage(p: &mut Process, nb_processors: u64, now: ULARGE_INTEGER) { unsafe { let mut sys: ULARGE_INTEGER = ::std::mem::zeroed(); @@ -700,7 +671,6 @@ pub fn get_handle(p: &Process) -> HANDLE { pub fn update_proc_info(p: &mut Process) { update_memory(p); - get_disk_usage(p); } pub fn update_memory(p: &mut Process) { diff --git a/src/windows/system.rs b/src/windows/system.rs index d03eb3a19..1ab9a72fd 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -23,7 +23,7 @@ use SystemExt; use User; use windows::process::{ - compute_cpu_usage, get_disk_usage, get_handle, get_system_computation_time, update_proc_info, + compute_cpu_usage, get_handle, get_system_computation_time, update_proc_info, Process, }; use windows::tools::*; @@ -65,19 +65,6 @@ struct Wrap(T); unsafe impl Send for Wrap {} unsafe impl Sync for Wrap {} -unsafe fn boot_time() -> u64 { - match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { - Ok(n) => n.as_secs() - GetTickCount64() / 1000, - Err(_e) => { - #[cfg(feature = "debug")] - { - println!("Failed to compute boot time: {:?}", _e); - } - 0 - } - } -} - #[cfg(feature = "debug")] macro_rules! sysinfo_debug { ($($x:tt)*) => {{ @@ -90,6 +77,15 @@ macro_rules! sysinfo_debug { ($($x:tt)*) => {{}} } +unsafe fn boot_time() -> u64 { + match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { + Ok(n) => n.as_secs() - GetTickCount64() / 1000, + Err(_e) => { + sysinfo_debug!("Failed to compute boot time: {:?}", _e); + 0 + } + } +} impl SystemExt for System { #[allow(non_snake_case)] fn new_with_specifics(refreshes: RefreshKind) -> System { @@ -276,7 +272,6 @@ impl SystemExt for System { proc_.memory = (pi.WorkingSetSize as u64) >> 10u64; proc_.virtual_memory = (pi.VirtualSize as u64) >> 10u64; compute_cpu_usage(proc_, nb_processors, system_time); - get_disk_usage(proc_); proc_.updated = true; return None; } @@ -292,7 +287,6 @@ impl SystemExt for System { (pi.VirtualSize as u64) >> 10u64, name, ); - get_disk_usage(&mut p); compute_cpu_usage(&mut p, nb_processors, system_time); Some(p) }) From 6b6c08d15ee327b86b51ec66a19723fd3625f7e1 Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Sun, 5 Apr 2020 14:13:56 +0200 Subject: [PATCH 15/28] fmt --- src/debug.rs | 10 ++++++++-- src/sysinfo.rs | 4 +++- tests/process.rs | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/debug.rs b/src/debug.rs index 73ca2732d..e70e9874d 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -131,11 +131,17 @@ impl fmt::Debug for NetworkData { .field("packets income", &self.get_packets_received()) .field("total packets income", &self.get_total_packets_received()) .field("packets outcome", &self.get_packets_transmitted()) - .field("total packets outcome", &self.get_total_packets_transmitted()) + .field( + "total packets outcome", + &self.get_total_packets_transmitted(), + ) .field("errors income", &self.get_errors_on_received()) .field("total errors income", &self.get_total_errors_on_received()) .field("errors outcome", &self.get_errors_on_transmitted()) - .field("total errors outcome", &self.get_total_errors_on_transmitted()) + .field( + "total errors outcome", + &self.get_total_errors_on_transmitted(), + ) .finish() } } diff --git a/src/sysinfo.rs b/src/sysinfo.rs index 3c55df04f..f040d9bab 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -92,7 +92,9 @@ cfg_if! { } } -pub use common::{AsU32, DiskType, DiskUsage, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, User}; +pub use common::{ + AsU32, DiskType, DiskUsage, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, User, +}; pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System}; pub use traits::{ ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt, diff --git a/tests/process.rs b/tests/process.rs index c8b0b013f..d38d9165f 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -63,12 +63,12 @@ fn test_get_cmd_line() { #[test] fn test_process_disk_usage() { - use sysinfo::{ProcessExt, SystemExt, get_current_pid}; - use std::fs::File; use std::fs; use std::fs::File; + use std::fs::File; use std::io::prelude::*; use sysinfo::{get_current_pid, ProcessExt, SystemExt}; + use sysinfo::{get_current_pid, ProcessExt, SystemExt}; { let mut file = File::create("test.txt").unwrap(); file.write_all(b"This is a test file\nwith test data.\n") From 3e08ce66ff3020f55f3886e64ad40f1fdba9e51a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Apr 2020 17:20:37 +0200 Subject: [PATCH 16/28] Update mac performances --- README.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 74ebc4d93..81e66c84d 100644 --- a/README.md +++ b/README.md @@ -152,20 +152,21 @@ test bench_refresh_system ... bench: 1,214,780 ns/iter (+/- 52,013)
```text -test bench_new ... bench: 56,861 ns/iter (+/- 5,653) -test bench_new_all ... bench: 4,634,509 ns/iter (+/- 1,604,369) -test bench_refresh_all ... bench: 1,962,343 ns/iter (+/- 129,726) -test bench_refresh_components ... bench: 294,752 ns/iter (+/- 45,107) -test bench_refresh_components_list ... bench: 895,672 ns/iter (+/- 112,586) -test bench_refresh_cpu ... bench: 11,187 ns/iter (+/- 2,483) -test bench_refresh_disks ... bench: 975 ns/iter (+/- 50) -test bench_refresh_disks_lists ... bench: 25,955 ns/iter (+/- 3,159) -test bench_refresh_memory ... bench: 3,440 ns/iter (+/- 198) -test bench_refresh_networks ... bench: 211,552 ns/iter (+/- 16,686) -test bench_refresh_networks_list ... bench: 211,138 ns/iter (+/- 22,644) -test bench_refresh_process ... bench: 4,174 ns/iter (+/- 1,249) -test bench_refresh_processes ... bench: 803,559 ns/iter (+/- 42,974) -test bench_refresh_system ... bench: 365,762 ns/iter (+/- 55,893) +test bench_new ... bench: 86,404 ns/iter (+/- 9,402) +test bench_new_all ... bench: 21,123,771 ns/iter (+/- 570,722) +test bench_refresh_all ... bench: 1,757,683 ns/iter (+/- 203,234) +test bench_refresh_components ... bench: 325,560 ns/iter (+/- 41,068) +test bench_refresh_components_list ... bench: 989,827 ns/iter (+/- 221,093) +test bench_refresh_cpu ... bench: 8,535 ns/iter (+/- 487) +test bench_refresh_disks ... bench: 939 ns/iter (+/- 33) +test bench_refresh_disks_lists ... bench: 25,093 ns/iter (+/- 2,080) +test bench_refresh_memory ... bench: 2,174 ns/iter (+/- 55) +test bench_refresh_networks ... bench: 181,558 ns/iter (+/- 7,325) +test bench_refresh_networks_list ... bench: 180,410 ns/iter (+/- 2,414) +test bench_refresh_process ... bench: 5,570 ns/iter (+/- 431) +test bench_refresh_processes ... bench: 683,455 ns/iter (+/- 14,995) +test bench_refresh_system ... bench: 362,875 ns/iter (+/- 172,547) +test bench_refresh_users_list ... bench: 16,783,834 ns/iter (+/- 465,111) ```
From bd40c05366ed717bc3675c232df63651980fb4f5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Apr 2020 17:21:00 +0200 Subject: [PATCH 17/28] Update ProcessExt::get_disk_usage --- src/common.rs | 10 +++++++++- src/traits.rs | 6 +++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/common.rs b/src/common.rs index 80832e839..72cc3a617 100644 --- a/src/common.rs +++ b/src/common.rs @@ -410,17 +410,25 @@ impl UserExt for User { /// let s = System::new_all(); /// for (pid, process) in s.get_processes() { /// let disk_usage = process.get_disk_usage(); -/// println!("[{}] read/written bytes: {}/{}", +/// println!("[{}] read bytes : new/total => {}/{}", /// pid, /// disk_usage.read_bytes, +/// disk_usage.total_read_bytes, +/// ); +/// println!("[{}] written bytes: new/total => {}/{}", /// disk_usage.written_bytes, +/// disk_usage.total_written_bytes, /// ); /// } /// ``` #[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)] pub struct DiskUsage { + /// Total number of written bytes. + pub total_written_bytes: u64, /// Number of written bytes. pub written_bytes: u64, + /// Total number of read bytes. + pub total_read_bytes: u64, /// Number of read bytes. pub read_bytes: u64, } diff --git a/src/traits.rs b/src/traits.rs index 1f5ee7347..f14bc2a80 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -305,9 +305,13 @@ pub trait ProcessExt: Debug { /// let s = System::new(); /// if let Some(process) = s.get_process(1337) { /// let disk_usage = process.get_disk_usage(); - /// println!("read/written bytes: {}/{}", + /// println!("read bytes : new/total => {}/{}", /// disk_usage.read_bytes, + /// disk_usage.total_read_bytes, + /// ); + /// println!("written bytes: new/total => {}/{}", /// disk_usage.written_bytes, + /// disk_usage.total_written_bytes, /// ); /// } /// ``` From 7a1b80ee02063089ed66e2d4562bbf9fe27f0abb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Apr 2020 17:21:15 +0200 Subject: [PATCH 18/28] Clean up mac disk usage code --- src/mac/ffi.rs | 8 ++------ src/mac/process.rs | 37 +++++++++++++++++++++++-------------- src/sysinfo.rs | 14 ++++++++++++++ src/windows/system.rs | 12 ------------ 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/mac/ffi.rs b/src/mac/ffi.rs index 97fd3d555..8fc30d1bd 100644 --- a/src/mac/ffi.rs +++ b/src/mac/ffi.rs @@ -30,6 +30,7 @@ extern "C" { //pub fn proc_regionfilename(pid: c_int, address: u64, buffer: *mut c_void, // buffersize: u32) -> c_int; pub fn proc_pidpath(pid: c_int, buffer: *mut c_void, buffersize: u32) -> c_int; + pub fn proc_pid_rusage(pid: c_int, flavor: c_int, buffer: *mut c_void) -> c_int; pub fn IOMasterPort(a: i32, b: *mut mach_port_t) -> i32; pub fn IOServiceMatching(a: *const c_char) -> *mut c_void; @@ -130,11 +131,6 @@ extern "C" { // pub fn proc_name(pid: i32, buf: *mut i8, bufsize: u32) -> i32; } -#[link(name = "proc", kind = "dylib")] -extern "C" { - pub fn proc_pid_rusage(pid: c_int, flavor: c_int, buffer: *mut c_void) -> c_int; -} - // TODO: waiting for https://github.com/rust-lang/libc/pull/678 macro_rules! cfg_if { ($( @@ -437,8 +433,8 @@ pub struct xsw_usage { } //https://github.com/andrewdavidmackenzie/libproc-rs/blob/master/src/libproc/pid_rusage.rs -#[repr(C)] #[derive(Debug, Default)] +#[repr(C)] pub struct RUsageInfoV2 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, diff --git a/src/mac/process.rs b/src/mac/process.rs index c23ed8726..41adebf1a 100644 --- a/src/mac/process.rs +++ b/src/mac/process.rs @@ -7,12 +7,13 @@ use std::borrow::Borrow; use std::ffi::OsStr; use std::fmt; -use std::mem; +use std::mem::{self, MaybeUninit}; use std::ops::Deref; use std::path::{Path, PathBuf}; use libc::{c_int, c_void, gid_t, kill, size_t, uid_t}; +use DiskUsage; use Pid; use ProcessExt; @@ -149,6 +150,8 @@ pub struct Process { /// /// This is very likely this one that you want instead of `process_status`. pub status: Option, + pub(crate) old_read_bytes: u64, + pub(crate) old_written_bytes: u64, pub(crate) read_bytes: u64, pub(crate) written_bytes: u64, } @@ -177,6 +180,8 @@ impl Process { gid: 0, process_status: ProcessStatus::Unknown(0), status: None, + old_read_bytes: 0, + old_written_bytes: 0, read_bytes: 0, written_bytes: 0, } @@ -214,6 +219,8 @@ impl Process { gid: 0, process_status: ProcessStatus::Unknown(0), status: None, + old_read_bytes: 0, + old_written_bytes: 0, read_bytes: 0, written_bytes: 0, } @@ -244,6 +251,8 @@ impl ProcessExt for Process { gid: 0, process_status: ProcessStatus::Unknown(0), status: None, + old_read_bytes: 0, + old_written_bytes: 0, read_bytes: 0, written_bytes: 0, } @@ -305,12 +314,13 @@ impl ProcessExt for Process { self.cpu_usage } - fn read_bytes(&self) -> u64 { - self.read_bytes - } - - fn written_bytes(&self) -> u64 { - self.written_bytes + fn get_disk_usage(&self) -> DiskUsage { + DiskUsage { + read_bytes: self.read_bytes - self.old_read_bytes, + total_read_bytes: self.read_bytes, + written_bytes: self.written_bytes - self.old_written_bytes, + total_written_bytes: self.written_bytes, + } } } @@ -595,15 +605,14 @@ pub(crate) fn update_process( } fn update_proc_disk_activity(p: &mut Process) { - let mut pidrusage = ffi::RUsageInfoV2::default(); - let ptr = &mut pidrusage as *mut _ as *mut c_void; - let retval: i32; - unsafe { - retval = ffi::proc_pid_rusage(p.pid() as c_int, 2, ptr); - } + p.old_read_bytes = p.read_bytes; + p.old_written_bytes = p.written_bytes; + + let mut pidrusage: ffi::RUsageInfoV2 = unsafe { MaybeUninit::uninit().assume_init() }; + let retval = unsafe { ffi::proc_pid_rusage(p.pid() as c_int, 2, &mut pidrusage as *mut _ as _) }; if retval < 0 { - panic!("proc_pid_rusage failed: {:?}", retval); + sysinfo_debug!("proc_pid_rusage failed: {:?}", retval); } else { p.read_bytes = pidrusage.ri_diskio_bytesread; p.written_bytes = pidrusage.ri_diskio_byteswritten; diff --git a/src/sysinfo.rs b/src/sysinfo.rs index f040d9bab..5e9ee8bf3 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -61,6 +61,20 @@ extern crate doc_comment; #[cfg(doctest)] doctest!("../README.md"); +#[cfg(feature = "debug")] +#[doc(hidden)] +macro_rules! sysinfo_debug { + ($($x:tt)*) => {{ + eprintln!($($x)*); + }} +} + +#[cfg(not(feature = "debug"))] +#[doc(hidden)] +macro_rules! sysinfo_debug { + ($($x:tt)*) => {{}} +} + cfg_if! { if #[cfg(target_os = "macos")] { mod mac; diff --git a/src/windows/system.rs b/src/windows/system.rs index 1ab9a72fd..dae583c39 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -65,18 +65,6 @@ struct Wrap(T); unsafe impl Send for Wrap {} unsafe impl Sync for Wrap {} -#[cfg(feature = "debug")] -macro_rules! sysinfo_debug { - ($($x:tt)*) => {{ - eprintln!($($x)*); - }} -} - -#[cfg(not(feature = "debug"))] -macro_rules! sysinfo_debug { - ($($x:tt)*) => {{}} -} - unsafe fn boot_time() -> u64 { match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { Ok(n) => n.as_secs() - GetTickCount64() / 1000, From db7931017841647c3a568d5e330dedaeec178e24 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Apr 2020 17:22:01 +0200 Subject: [PATCH 19/28] Fix bench typo --- benches/basic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/basic.rs b/benches/basic.rs index 0666a050f..b1464939b 100644 --- a/benches/basic.rs +++ b/benches/basic.rs @@ -71,7 +71,7 @@ fn bench_refresh_disks(b: &mut test::Bencher) { } #[bench] -fn bench_refresh_disks_lists(b: &mut test::Bencher) { +fn bench_refresh_disks_list(b: &mut test::Bencher) { let mut s = sysinfo::System::new(); b.iter(move || { From 49b3e1031364303ed0457f6da95e2ca35633de5a Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Sun, 5 Apr 2020 17:52:26 +0200 Subject: [PATCH 20/28] Update windows bench results --- README.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 81e66c84d..c9509e8b1 100644 --- a/README.md +++ b/README.md @@ -130,20 +130,21 @@ test bench_refresh_system ... bench: 52,466 ns/iter (+/- 4,710)
```text -test bench_new ... bench: 7,688,460 ns/iter (+/- 1,230,010) -test bench_new_all ... bench: 24,098,860 ns/iter (+/- 5,260,950) -test bench_refresh_all ... bench: 3,096,107 ns/iter (+/- 94,257) -test bench_refresh_components ... bench: 1,205,378 ns/iter (+/- 40,071) -test bench_refresh_components_list ... bench: 3,181,602 ns/iter (+/- 102,533) -test bench_refresh_cpu ... bench: 395 ns/iter (+/- 18) -test bench_refresh_disks ... bench: 53,082 ns/iter (+/- 1,834) -test bench_refresh_disks_lists ... bench: 114,080 ns/iter (+/- 1,920) -test bench_refresh_memory ... bench: 596 ns/iter (+/- 48) -test bench_refresh_networks ... bench: 37,549 ns/iter (+/- 1,622) -test bench_refresh_networks_list ... bench: 667,180 ns/iter (+/- 59,859) -test bench_refresh_process ... bench: 755 ns/iter (+/- 47) -test bench_refresh_processes ... bench: 1,217,488 ns/iter (+/- 69,041) -test bench_refresh_system ... bench: 1,214,780 ns/iter (+/- 52,013) +test bench_new ... bench: 7,778,330 ns/iter (+/- 355,054) +test bench_new_all ... bench: 85,655,800 ns/iter (+/- 2,082,645) +test bench_refresh_all ... bench: 1,404,736 ns/iter (+/- 106,109) +test bench_refresh_components ... bench: 1 ns/iter (+/- 0) +test bench_refresh_components_list ... bench: 29,210 ns/iter (+/- 2,278) +test bench_refresh_cpu ... bench: 34,225 ns/iter (+/- 29,786) +test bench_refresh_disks ... bench: 54,453 ns/iter (+/- 2,751) +test bench_refresh_disks_list ... bench: 125,164 ns/iter (+/- 2,692) +test bench_refresh_memory ... bench: 1,007 ns/iter (+/- 38) +test bench_refresh_networks ... bench: 38,753 ns/iter (+/- 2,527) +test bench_refresh_networks_list ... bench: 1,352,400 ns/iter (+/- 146,762) +test bench_refresh_process ... bench: 1,284 ns/iter (+/- 71) +test bench_refresh_processes ... bench: 1,045,020 ns/iter (+/- 77,908) +test bench_refresh_system ... bench: 35,787 ns/iter (+/- 3,587) +test bench_refresh_users_list ... bench: 3,339,050 ns/iter (+/- 172,762) ```
From de90886afa7589add1c0d6ec70b950ede768b4f9 Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Sun, 5 Apr 2020 17:52:41 +0200 Subject: [PATCH 21/28] Update windows to new DiskUsage --- src/windows/process.rs | 87 +++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 17 deletions(-) diff --git a/src/windows/process.rs b/src/windows/process.rs index ca571df40..0643d407c 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -4,6 +4,7 @@ // Copyright (c) 2018 Guillaume Gomez // +use std::cell::RefCell; use std::fmt::{self, Debug}; use std::mem::{size_of, zeroed, MaybeUninit}; use std::ops::Deref; @@ -82,6 +83,20 @@ impl Deref for PtrWrapper { unsafe impl Send for PtrWrapper {} unsafe impl Sync for PtrWrapper {} +#[derive(Default)] +struct DiskBytes { + written_bytes: u64, + read_bytes: u64, +} + +struct DiskInfo { + diag_info: PtrWrapper>, + old_disk_bytes: RefCell, +} + +unsafe impl Send for DiskInfo {} +unsafe impl Sync for DiskInfo {} + /// Struct containing a process' information. pub struct Process { name: String, @@ -102,7 +117,7 @@ pub struct Process { start_time: u64, cpu_usage: f32, pub(crate) updated: bool, - diag_info: Option>>, + disk_info: Option, } unsafe fn get_process_name(process_handler: HANDLE, h_mod: *mut c_void) -> String { @@ -221,11 +236,14 @@ impl Process { old_user_cpu: 0, start_time: unsafe { get_start_time(handle) }, updated: true, - diag_info: + disk_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() .and_then(|x| x) - .map(|x| PtrWrapper(x)) + .map(|x| DiskInfo { + diag_info: PtrWrapper(x), + old_disk_bytes: RefCell::new(DiskBytes::default()), + }) } } else { Process { @@ -247,11 +265,14 @@ impl Process { old_user_cpu: 0, start_time: 0, updated: true, - diag_info: + disk_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() .and_then(|x| x) - .map(|x| PtrWrapper(x)) + .map(|x| DiskInfo { + diag_info: PtrWrapper(x), + old_disk_bytes: RefCell::new(DiskBytes::default()), + }) } } } @@ -289,11 +310,14 @@ impl Process { old_user_cpu: 0, start_time: get_start_time(process_handler), updated: true, - diag_info: + disk_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() .and_then(|x| x) - .map(|x| PtrWrapper(x)) + .map(|x| DiskInfo { + diag_info: PtrWrapper(x), + old_disk_bytes: RefCell::new(DiskBytes::default()), + }) } } } @@ -328,11 +352,14 @@ impl ProcessExt for Process { old_user_cpu: 0, start_time: 0, updated: true, - diag_info: + disk_info: ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) .ok() .and_then(|x| x) - .map(|x| PtrWrapper(x)) + .map(|x| DiskInfo { + diag_info: PtrWrapper(x), + old_disk_bytes: RefCell::new(DiskBytes::default()), + }) } } } @@ -399,20 +426,46 @@ impl ProcessExt for Process { } fn get_disk_usage(&self) -> DiskUsage { - if let Some(ref diag_info) = self.diag_info { - let disk_usage = match diag_info.get_disk_usage().ok() { + if let Some(ref disk_info) = self.disk_info { + let disk_usage = match disk_info.diag_info.get_disk_usage().ok() { Some(Some(d)) => d, - _ => return DiskUsage::default(), + _ => { + let tmp = disk_info.old_disk_bytes.borrow(); + return DiskUsage { + total_read_bytes: tmp.read_bytes, + read_bytes: 0, + total_written_bytes: tmp.written_bytes, + written_bytes: 0, + }; + } }; let report = match disk_usage.get_report().ok() { Some(Some(d)) => d, - _ => return DiskUsage::default(), + _ => { + let tmp = disk_info.old_disk_bytes.borrow(); + return DiskUsage { + total_read_bytes: tmp.read_bytes, + read_bytes: 0, + total_written_bytes: tmp.written_bytes, + written_bytes: 0, + }; + } + }; + let (read_bytes, written_bytes, old_read_bytes, old_written_bytes) = { + let mut tmp = disk_info.old_disk_bytes.borrow_mut(); + let read_bytes = report.get_bytes_read_count().ok().map(|x| x as u64).unwrap_or(tmp.read_bytes); + let written_bytes = report.get_bytes_written_count().ok().map(|x| x as u64).unwrap_or(tmp.written_bytes); + let old_read_bytes = tmp.read_bytes; + let old_written_bytes = tmp.written_bytes; + tmp.read_bytes = read_bytes; + tmp.written_bytes = written_bytes; + (read_bytes, written_bytes, old_read_bytes, old_written_bytes) }; - let read_bytes = report.get_bytes_read_count().ok().map(|x| x as u64); - let written_bytes = report.get_bytes_written_count().ok().map(|x| x as u64); DiskUsage { - read_bytes: read_bytes.unwrap_or(0), - written_bytes: written_bytes.unwrap_or(0), + total_read_bytes: read_bytes, + read_bytes: read_bytes - old_read_bytes, + total_written_bytes: written_bytes, + written_bytes: written_bytes - old_written_bytes, } } else { DiskUsage::default() From 9ad5fe662aa27fce1b2e0ebaad55f1d26995b5bc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Apr 2020 23:39:00 +0200 Subject: [PATCH 22/28] Update linux API --- src/linux/process.rs | 51 +++++++++++++++++++++++++++++++++++++------- src/linux/system.rs | 25 +++------------------- src/traits.rs | 2 ++ 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/linux/process.rs b/src/linux/process.rs index 4840cc078..f2fbe69f9 100644 --- a/src/linux/process.rs +++ b/src/linux/process.rs @@ -11,6 +11,7 @@ use std::path::{Path, PathBuf}; use libc::{c_int, gid_t, kill, uid_t}; +use DiskUsage; use Pid; use ProcessExt; @@ -124,8 +125,10 @@ pub struct Process { /// Tasks run by this process. pub tasks: HashMap, pub(crate) stat_file: Option, - pub(crate) read_bytes: u64, - pub(crate) written_bytes: u64, + old_read_bytes: u64, + old_written_bytes: u64, + read_bytes: u64, + written_bytes: u64, } impl ProcessExt for Process { @@ -157,6 +160,8 @@ impl ProcessExt for Process { HashMap::new() }, stat_file: None, + old_read_bytes: 0, + old_written_bytes: 0, read_bytes: 0, written_bytes: 0, } @@ -220,12 +225,13 @@ impl ProcessExt for Process { self.cpu_usage } - fn read_bytes(&self) -> u64 { - self.read_bytes - } - - fn written_bytes(&self) -> u64 { - self.written_bytes + fn get_disk_usage(&self) -> DiskUsage { + DiskUsage { + written_bytes: self.written_bytes - self.old_written_bytes, + total_written_bytes: self.written_bytes, + read_bytes: self.read_bytes - self.old_read_bytes, + total_read_bytes: self.read_bytes, + } } } @@ -256,3 +262,32 @@ pub fn set_time(p: &mut Process, utime: u64, stime: u64) { pub fn has_been_updated(p: &Process) -> bool { p.updated } + +pub(crate) fn update_process_disk_activity(p: &mut Process, path: &Path) { + let mut path = PathBuf::from(path); + path.push("io"); + let data = match super::system::get_all_data(&path, 16_384) { + Ok(d) => d, + Err(_) => return, + }; + let mut done = 0; + for line in data.split("\n") { + let mut parts = line.split(": "); + match parts.next() { + Some("read_bytes") => { + p.old_read_bytes = p.read_bytes; + p.read_bytes = parts.next().and_then(|x| x.parse::().ok()).unwrap_or(0); + } + Some("write_bytes") => { + p.old_written_bytes = p.written_bytes; + p.written_bytes = parts.next().and_then(|x| x.parse::().ok()).unwrap_or(0); + } + _ => continue, + } + done += 1; + if done > 1 { + // No need to continue the reading. + break; + } + } +} diff --git a/src/linux/system.rs b/src/linux/system.rs index 2b5e435d8..efd498a50 100644 --- a/src/linux/system.rs +++ b/src/linux/system.rs @@ -120,10 +120,7 @@ fn boot_time() -> u64 { if unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut up) } == 0 { up.tv_sec as u64 } else { - #[cfg(feature = "debug")] - { - println!("clock_gettime failed: boot time cannot be retrieve..."); - } + sysinfo_debug!("clock_gettime failed: boot time cannot be retrieve..."); 0 } } @@ -738,7 +735,7 @@ fn _get_process_data( uptime, now, ); - update_process_disk_activity(entry); + update_process_disk_activity(entry, path); return Ok(None); } @@ -822,26 +819,10 @@ fn _get_process_data( uptime, now, ); - update_process_disk_activity(&mut p); + update_process_disk_activity(&mut p, path); Ok(Some(p)) } -fn update_process_disk_activity(p: &mut Process) { - let path = PathBuf::from(format!("/proc/{}/io", p.pid)); - let data = match get_all_data(&path, 16_384) { - Ok(d) => d, - Err(_) => return, - }; - let data: Vec> = data.split("\n").map(|l| l.split(": ").collect()).collect(); - for d in data.iter() { - if d[0] == "read_bytes" { - p.read_bytes = d[1].parse::().unwrap_or(0); - } else if d[0] == "write_bytes" { - p.written_bytes = d[1].parse::().unwrap_or(0); - } - } -} - fn copy_from_file(entry: &Path) -> Vec { match File::open(entry.to_str().unwrap_or("/")) { Ok(mut f) => { diff --git a/src/traits.rs b/src/traits.rs index f14bc2a80..c3eec4635 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -299,6 +299,8 @@ pub trait ProcessExt: Debug { /// Returns number of bytes read and written to disk. /// + /// **On Windows, the disk usage is computed when calling this method!** + /// /// ```no_run /// use sysinfo::{ProcessExt, System, SystemExt}; /// From 94396b21d3dfe944ae86cd5c77ae8d4a44623397 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Apr 2020 23:39:09 +0200 Subject: [PATCH 23/28] Update linux benchmarks --- README.md | 29 +++++++++++++++-------------- src/sysinfo.rs | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c9509e8b1..3cc86429b 100644 --- a/README.md +++ b/README.md @@ -108,20 +108,21 @@ Here are the current results:
```text -test bench_new ... bench: 3,741 ns/iter (+/- 252) -test bench_new_all ... bench: 10,491,084 ns/iter (+/- 450,925) -test bench_refresh_all ... bench: 2,787,974 ns/iter (+/- 235,649) -test bench_refresh_components ... bench: 24,270 ns/iter (+/- 1,127) -test bench_refresh_components_list ... bench: 370,693 ns/iter (+/- 51,925) -test bench_refresh_cpu ... bench: 13,367 ns/iter (+/- 1,858) -test bench_refresh_disks ... bench: 2,532 ns/iter (+/- 108) -test bench_refresh_disks_lists ... bench: 50,359 ns/iter (+/- 5,877) -test bench_refresh_memory ... bench: 11,713 ns/iter (+/- 1,006) -test bench_refresh_networks ... bench: 220,246 ns/iter (+/- 24,294) -test bench_refresh_networks_list ... bench: 229,648 ns/iter (+/- 82,050) -test bench_refresh_process ... bench: 77,375 ns/iter (+/- 10,657) -test bench_refresh_processes ... bench: 2,282,106 ns/iter (+/- 154,098) -test bench_refresh_system ... bench: 52,466 ns/iter (+/- 4,710) +test bench_new ... bench: 186,638 ns/iter (+/- 8,603) +test bench_new_all ... bench: 18,604,576 ns/iter (+/- 1,323,790) +test bench_refresh_all ... bench: 5,147,523 ns/iter (+/- 337,096) +test bench_refresh_components ... bench: 25,391 ns/iter (+/- 1,725) +test bench_refresh_components_list ... bench: 381,490 ns/iter (+/- 18,237) +test bench_refresh_cpu ... bench: 13,397 ns/iter (+/- 880) +test bench_refresh_disks ... bench: 2,515 ns/iter (+/- 161) +test bench_refresh_disks_list ... bench: 50,986 ns/iter (+/- 5,301) +test bench_refresh_memory ... bench: 11,843 ns/iter (+/- 779) +test bench_refresh_networks ... bench: 250,242 ns/iter (+/- 68,482) +test bench_refresh_networks_list ... bench: 255,148 ns/iter (+/- 23,677) +test bench_refresh_process ... bench: 128,860 ns/iter (+/- 22,638) +test bench_refresh_processes ... bench: 4,714,965 ns/iter (+/- 309,573) +test bench_refresh_system ... bench: 52,044 ns/iter (+/- 4,510) +test bench_refresh_users_list ... bench: 2,095,043 ns/iter (+/- 648,385) ```
diff --git a/src/sysinfo.rs b/src/sysinfo.rs index 5e9ee8bf3..40aa1e05a 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -72,7 +72,7 @@ macro_rules! sysinfo_debug { #[cfg(not(feature = "debug"))] #[doc(hidden)] macro_rules! sysinfo_debug { - ($($x:tt)*) => {{}} + ($($x:tt)*) => {{}}; } cfg_if! { From 60feb1c4718d20dedcd312b080223044d55aa165 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 5 Apr 2020 23:43:20 +0200 Subject: [PATCH 24/28] Update tests --- src/common.rs | 1 + tests/process.rs | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common.rs b/src/common.rs index 72cc3a617..1d0fe7752 100644 --- a/src/common.rs +++ b/src/common.rs @@ -416,6 +416,7 @@ impl UserExt for User { /// disk_usage.total_read_bytes, /// ); /// println!("[{}] written bytes: new/total => {}/{}", +/// pid, /// disk_usage.written_bytes, /// disk_usage.total_written_bytes, /// ); diff --git a/tests/process.rs b/tests/process.rs index d38d9165f..89fdef952 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -65,20 +65,19 @@ fn test_get_cmd_line() { fn test_process_disk_usage() { use std::fs; use std::fs::File; - use std::fs::File; use std::io::prelude::*; use sysinfo::{get_current_pid, ProcessExt, SystemExt}; - use sysinfo::{get_current_pid, ProcessExt, SystemExt}; { let mut file = File::create("test.txt").unwrap(); file.write_all(b"This is a test file\nwith test data.\n") .unwrap(); } fs::remove_file("test.txt").ok(); - let system = sysinfo::System::new(); + let mut system = sysinfo::System::new(); + system.refresh_processes(); let p = system .get_process(get_current_pid().expect("Failed retrieving current pid.")) .expect("failed to get process"); - assert!(p.written_bytes() > 0); + assert!(p.get_disk_usage().total_written_bytes > 0); } From 864377c1e629495230a331245c54ce282e4401b7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 6 Apr 2020 00:00:31 +0200 Subject: [PATCH 25/28] Update unknown targets API --- src/unknown/process.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/unknown/process.rs b/src/unknown/process.rs index d79bafd7d..b55884f5e 100644 --- a/src/unknown/process.rs +++ b/src/unknown/process.rs @@ -5,6 +5,7 @@ // use std::path::Path; +use DiskUsage; use Pid; use ProcessExt; @@ -79,4 +80,8 @@ impl ProcessExt for Process { fn cpu_usage(&self) -> f32 { 0.0 } + + fn get_disk_usage(&self) -> DiskUsage { + DiskUsage::default() + } } From 202000ecccc4d40f82aff50ffe37661e9aaa6833 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 6 Apr 2020 00:01:55 +0200 Subject: [PATCH 26/28] Fix doc links --- src/common.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common.rs b/src/common.rs index 1d0fe7752..3655cb22f 100644 --- a/src/common.rs +++ b/src/common.rs @@ -349,7 +349,7 @@ pub enum Signal { /// A struct representing system load average value. /// -/// It is returned by [`SystemExt::get_load_average`]. +/// It is returned by [`SystemExt::get_load_average`][crate::SystemExt::get_load_average]. /// /// ```no_run /// use sysinfo::{System, SystemExt}; @@ -376,7 +376,7 @@ pub struct LoadAvg { /// Type containing user information. /// -/// It is returned by [`SystemExt::get_users`]. +/// It is returned by [`SystemExt::get_users`][crate::SystemExt::get_users]. /// /// ```no_run /// use sysinfo::{System, SystemExt}; @@ -402,7 +402,7 @@ impl UserExt for User { /// Type containing read and written bytes. /// -/// It is returned by [`ProcessExt::get_disk_usage`]. +/// It is returned by [`ProcessExt::get_disk_usage`][crate::ProcessExt::get_disk_usage]. /// /// ```no_run /// use sysinfo::{ProcessExt, System, SystemExt}; From bf16c486695bdd111f796cff053e858353e7f18d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 6 Apr 2020 14:48:01 +0200 Subject: [PATCH 27/28] Check if a winrt functionality is available before using it --- Cargo.toml | 2 +- src/windows/process.rs | 56 +++++++++++++----------------- src/windows/system.rs | 78 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 94 insertions(+), 42 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 892f8e7ff..3159c90ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ doc-comment = "0.3" once_cell = "1.0" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["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"] } +winapi = { version = "0.3", features = ["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", "roapi"] } ntapi = "0.3" winrt = { version = "0.6.0", features = ["windows-system"]} diff --git a/src/windows/process.rs b/src/windows/process.rs index 0643d407c..3fc8d2413 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -170,6 +170,26 @@ unsafe fn get_exe(process_handler: HANDLE, h_mod: *mut c_void) -> PathBuf { PathBuf::from(String::from_utf16_lossy(&exe_buf[..pos])) } +fn get_disk_for_process_id(pid: u32) -> Option { + use super::system::{can_be_registered, RegistrationStatus}; + + match can_be_registered::() { + RegistrationStatus::Ok => { + ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) + .ok() + .and_then(|x| x) + .map(|x| DiskInfo { + diag_info: PtrWrapper(x), + old_disk_bytes: RefCell::new(DiskBytes::default()), + }) + } + _x => { + sysinfo_debug!("Cannot register AppDiagnosticInfo: {:?}", _x); + None + } + } +} + impl Process { #[allow(clippy::uninit_assumed_init)] pub(crate) fn new_from_pid(pid: Pid) -> Option { @@ -236,14 +256,7 @@ impl Process { old_user_cpu: 0, start_time: unsafe { get_start_time(handle) }, updated: true, - disk_info: - ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) - .ok() - .and_then(|x| x) - .map(|x| DiskInfo { - diag_info: PtrWrapper(x), - old_disk_bytes: RefCell::new(DiskBytes::default()), - }) + disk_info: get_disk_for_process_id(pid as u32), } } else { Process { @@ -265,14 +278,7 @@ impl Process { old_user_cpu: 0, start_time: 0, updated: true, - disk_info: - ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) - .ok() - .and_then(|x| x) - .map(|x| DiskInfo { - diag_info: PtrWrapper(x), - old_disk_bytes: RefCell::new(DiskBytes::default()), - }) + disk_info: get_disk_for_process_id(pid as u32), } } } @@ -310,14 +316,7 @@ impl Process { old_user_cpu: 0, start_time: get_start_time(process_handler), updated: true, - disk_info: - ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) - .ok() - .and_then(|x| x) - .map(|x| DiskInfo { - diag_info: PtrWrapper(x), - old_disk_bytes: RefCell::new(DiskBytes::default()), - }) + disk_info: get_disk_for_process_id(pid as u32), } } } @@ -352,14 +351,7 @@ impl ProcessExt for Process { old_user_cpu: 0, start_time: 0, updated: true, - disk_info: - ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) - .ok() - .and_then(|x| x) - .map(|x| DiskInfo { - diag_info: PtrWrapper(x), - old_disk_bytes: RefCell::new(DiskBytes::default()), - }) + disk_info: get_disk_for_process_id(pid as u32), } } } diff --git a/src/windows/system.rs b/src/windows/system.rs index dae583c39..17ab870ff 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -40,7 +40,7 @@ use winapi::um::sysinfoapi::{GetTickCount64, GlobalMemoryStatusEx, MEMORYSTATUSE use winapi::um::winnt::HANDLE; use rayon::prelude::*; use winrt::windows::system::{AppDiagnosticInfo, DiagnosticAccessStatus}; -use winrt::{RtAsyncOperation}; +use winrt::{RtAsyncOperation, RtActivatable}; /// Struct containing the system's information. pub struct System { @@ -74,19 +74,79 @@ unsafe fn boot_time() -> u64 { } } } + +// To be removed once winrt PR is merged! +#[derive(Clone, Copy, Debug, PartialEq)] +pub(crate) enum RegistrationStatus { + Ok, + NotRegistered, + Error(u32), +} + +// To be removed once winrt PR is merged! +pub(crate) fn can_be_registered>() -> RegistrationStatus { + use std::ptr; + use winapi::shared::ntdef::VOID; + use winapi::shared::winerror::{S_OK, CO_E_NOTINITIALIZED, REGDB_E_CLASSNOTREG}; + use winapi::um::combaseapi::CoIncrementMTAUsage; + use winapi::winrt::roapi::RoGetActivationFactory; + use winrt::{ComIid, HStringReference, RtType}; + + let mut res: ::Abi = unsafe { + ::uninitialized() + }; + let class_id = unsafe { HStringReference::from_utf16_unchecked(T::name()) }; + let mut hr = unsafe { + RoGetActivationFactory( + class_id.get(), + ::iid().as_ref(), + &mut res as *mut *mut _ as *mut *mut VOID, + ) + }; + if hr == CO_E_NOTINITIALIZED { + let mut cookie = ptr::null_mut(); + unsafe { CoIncrementMTAUsage(&mut cookie); } + hr = unsafe { + RoGetActivationFactory( + class_id.get(), + ::iid().as_ref(), + &mut res as *mut *mut _ as *mut *mut VOID, + ) + }; + } + if hr == S_OK { + RegistrationStatus::Ok + } else if hr == REGDB_E_CLASSNOTREG { + RegistrationStatus::NotRegistered + } else { + RegistrationStatus::Error(hr as u32) + } +} + impl SystemExt for System { #[allow(non_snake_case)] fn new_with_specifics(refreshes: RefreshKind) -> System { - match AppDiagnosticInfo::request_access_async() { - Ok(x) => { - match x.blocking_get() { - Ok(DiagnosticAccessStatus::Unspecified) => sysinfo_debug!("app diagnostic access refused: Unspecified"), - Ok(DiagnosticAccessStatus::Denied) => sysinfo_debug!("app diagnostic access refused: Denied"), - Ok(_) => {} - Err(_e) => sysinfo_debug!("failed to get access request status: {:?}", _e), + match can_be_registered::() { + RegistrationStatus::Ok => { + match AppDiagnosticInfo::request_access_async() { + Ok(x) => { + match x.blocking_get() { + Ok(DiagnosticAccessStatus::Unspecified) => { + sysinfo_debug!("app diagnostic access refused: Unspecified"); + } + Ok(DiagnosticAccessStatus::Denied) => { + sysinfo_debug!("app diagnostic access refused: Denied"); + } + Ok(_) => {} + Err(_e) => { + sysinfo_debug!("failed to get access request status: {:?}", _e); + } + } + } + Err(_e) => sysinfo_debug!("failed to request app diagnostic access: {:?}", _e), } } - Err(_e) => sysinfo_debug!("failed to request app diagnostic access: {:?}", _e), + _x => sysinfo_debug!("Cannot register AppDiagnosticInfo: {:?}", _x), } let (processors, vendor_id, brand) = init_processors(); let mut s = System { From 0f0ed78c3a2fafd9d1cbc6f9efd40edbe0647c0a Mon Sep 17 00:00:00 2001 From: GuillaumeGomez Date: Tue, 7 Apr 2020 20:38:45 +0200 Subject: [PATCH 28/28] Replace winrt with GetProcessIoCounters --- Cargo.toml | 3 +- README.md | 28 ++++----- src/sysinfo.rs | 1 - src/traits.rs | 2 +- src/windows/process.rs | 135 ++++++++++++++--------------------------- src/windows/system.rs | 77 ++--------------------- tests/process.rs | 29 ++++++++- 7 files changed, 91 insertions(+), 184 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3159c90ee..0f171f2b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,8 @@ doc-comment = "0.3" once_cell = "1.0" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["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", "roapi"] } +winapi = { version = "0.3", features = ["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"] } ntapi = "0.3" -winrt = { version = "0.6.0", features = ["windows-system"]} [target.'cfg(not(any(target_os = "unknown", target_arch = "wasm32")))'.dependencies] libc = "0.2" diff --git a/README.md b/README.md index 3cc86429b..45551fe85 100644 --- a/README.md +++ b/README.md @@ -131,21 +131,21 @@ test bench_refresh_users_list ... bench: 2,095,043 ns/iter (+/- 648,385)
```text -test bench_new ... bench: 7,778,330 ns/iter (+/- 355,054) -test bench_new_all ... bench: 85,655,800 ns/iter (+/- 2,082,645) -test bench_refresh_all ... bench: 1,404,736 ns/iter (+/- 106,109) +test bench_new ... bench: 7,335,755 ns/iter (+/- 469,000) +test bench_new_all ... bench: 32,233,480 ns/iter (+/- 1,567,239) +test bench_refresh_all ... bench: 1,433,015 ns/iter (+/- 126,322) test bench_refresh_components ... bench: 1 ns/iter (+/- 0) -test bench_refresh_components_list ... bench: 29,210 ns/iter (+/- 2,278) -test bench_refresh_cpu ... bench: 34,225 ns/iter (+/- 29,786) -test bench_refresh_disks ... bench: 54,453 ns/iter (+/- 2,751) -test bench_refresh_disks_list ... bench: 125,164 ns/iter (+/- 2,692) -test bench_refresh_memory ... bench: 1,007 ns/iter (+/- 38) -test bench_refresh_networks ... bench: 38,753 ns/iter (+/- 2,527) -test bench_refresh_networks_list ... bench: 1,352,400 ns/iter (+/- 146,762) -test bench_refresh_process ... bench: 1,284 ns/iter (+/- 71) -test bench_refresh_processes ... bench: 1,045,020 ns/iter (+/- 77,908) -test bench_refresh_system ... bench: 35,787 ns/iter (+/- 3,587) -test bench_refresh_users_list ... bench: 3,339,050 ns/iter (+/- 172,762) +test bench_refresh_components_list ... bench: 9,835,060 ns/iter (+/- 407,072) +test bench_refresh_cpu ... bench: 33,873 ns/iter (+/- 2,177) +test bench_refresh_disks ... bench: 58,951 ns/iter (+/- 6,128) +test bench_refresh_disks_list ... bench: 125,199 ns/iter (+/- 2,741) +test bench_refresh_memory ... bench: 1,004 ns/iter (+/- 56) +test bench_refresh_networks ... bench: 39,013 ns/iter (+/- 2,676) +test bench_refresh_networks_list ... bench: 1,341,850 ns/iter (+/- 78,258) +test bench_refresh_process ... bench: 2,116 ns/iter (+/- 58) +test bench_refresh_processes ... bench: 1,032,447 ns/iter (+/- 57,695) +test bench_refresh_system ... bench: 35,374 ns/iter (+/- 3,200) +test bench_refresh_users_list ... bench: 3,321,140 ns/iter (+/- 135,160) ```
diff --git a/src/sysinfo.rs b/src/sysinfo.rs index 40aa1e05a..2f25810fc 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -90,7 +90,6 @@ cfg_if! { #[cfg(test)] const MIN_USERS: usize = 1; - extern crate winrt; } else if #[cfg(unix)] { mod linux; use linux as sys; diff --git a/src/traits.rs b/src/traits.rs index c3eec4635..69ac35ee9 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -299,7 +299,7 @@ pub trait ProcessExt: Debug { /// Returns number of bytes read and written to disk. /// - /// **On Windows, the disk usage is computed when calling this method!** + /// /!\\ On Windows, this method actually returns **ALL** I/O read and written bytes. /// /// ```no_run /// use sysinfo::{ProcessExt, System, SystemExt}; diff --git a/src/windows/process.rs b/src/windows/process.rs index 3fc8d2413..a5e99450d 100644 --- a/src/windows/process.rs +++ b/src/windows/process.rs @@ -4,7 +4,6 @@ // Copyright (c) 2018 Guillaume Gomez // -use std::cell::RefCell; use std::fmt::{self, Debug}; use std::mem::{size_of, zeroed, MaybeUninit}; use std::ops::Deref; @@ -30,9 +29,8 @@ use winapi::um::psapi::{ LIST_MODULES_ALL, PROCESS_MEMORY_COUNTERS, PROCESS_MEMORY_COUNTERS_EX, }; use winapi::um::sysinfoapi::GetSystemTimeAsFileTime; -use winapi::um::winnt::{HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ, ULARGE_INTEGER}; -use winrt::windows::system::diagnostics::{ProcessDiagnosticInfo}; -use winrt::ComPtr; +use winapi::um::winbase::GetProcessIoCounters; +use winapi::um::winnt::{IO_COUNTERS, HANDLE, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ, ULARGE_INTEGER}; /// Enum describing the different status of a process. #[derive(Clone, Copy, Debug)] @@ -83,20 +81,6 @@ impl Deref for PtrWrapper { unsafe impl Send for PtrWrapper {} unsafe impl Sync for PtrWrapper {} -#[derive(Default)] -struct DiskBytes { - written_bytes: u64, - read_bytes: u64, -} - -struct DiskInfo { - diag_info: PtrWrapper>, - old_disk_bytes: RefCell, -} - -unsafe impl Send for DiskInfo {} -unsafe impl Sync for DiskInfo {} - /// Struct containing a process' information. pub struct Process { name: String, @@ -117,7 +101,10 @@ pub struct Process { start_time: u64, cpu_usage: f32, pub(crate) updated: bool, - disk_info: Option, + old_read_bytes: u64, + old_written_bytes: u64, + read_bytes: u64, + written_bytes: u64, } unsafe fn get_process_name(process_handler: HANDLE, h_mod: *mut c_void) -> String { @@ -170,26 +157,6 @@ unsafe fn get_exe(process_handler: HANDLE, h_mod: *mut c_void) -> PathBuf { PathBuf::from(String::from_utf16_lossy(&exe_buf[..pos])) } -fn get_disk_for_process_id(pid: u32) -> Option { - use super::system::{can_be_registered, RegistrationStatus}; - - match can_be_registered::() { - RegistrationStatus::Ok => { - ProcessDiagnosticInfo::try_get_for_process_id(pid as u32) - .ok() - .and_then(|x| x) - .map(|x| DiskInfo { - diag_info: PtrWrapper(x), - old_disk_bytes: RefCell::new(DiskBytes::default()), - }) - } - _x => { - sysinfo_debug!("Cannot register AppDiagnosticInfo: {:?}", _x); - None - } - } -} - impl Process { #[allow(clippy::uninit_assumed_init)] pub(crate) fn new_from_pid(pid: Pid) -> Option { @@ -256,7 +223,10 @@ impl Process { old_user_cpu: 0, start_time: unsafe { get_start_time(handle) }, updated: true, - disk_info: get_disk_for_process_id(pid as u32), + old_read_bytes: 0, + old_written_bytes: 0, + read_bytes: 0, + written_bytes: 0, } } else { Process { @@ -278,7 +248,10 @@ impl Process { old_user_cpu: 0, start_time: 0, updated: true, - disk_info: get_disk_for_process_id(pid as u32), + old_read_bytes: 0, + old_written_bytes: 0, + read_bytes: 0, + written_bytes: 0, } } } @@ -316,7 +289,10 @@ impl Process { old_user_cpu: 0, start_time: get_start_time(process_handler), updated: true, - disk_info: get_disk_for_process_id(pid as u32), + old_read_bytes: 0, + old_written_bytes: 0, + read_bytes: 0, + written_bytes: 0, } } } @@ -351,7 +327,10 @@ impl ProcessExt for Process { old_user_cpu: 0, start_time: 0, updated: true, - disk_info: get_disk_for_process_id(pid as u32), + old_read_bytes: 0, + old_written_bytes: 0, + read_bytes: 0, + written_bytes: 0, } } } @@ -418,49 +397,11 @@ impl ProcessExt for Process { } fn get_disk_usage(&self) -> DiskUsage { - if let Some(ref disk_info) = self.disk_info { - let disk_usage = match disk_info.diag_info.get_disk_usage().ok() { - Some(Some(d)) => d, - _ => { - let tmp = disk_info.old_disk_bytes.borrow(); - return DiskUsage { - total_read_bytes: tmp.read_bytes, - read_bytes: 0, - total_written_bytes: tmp.written_bytes, - written_bytes: 0, - }; - } - }; - let report = match disk_usage.get_report().ok() { - Some(Some(d)) => d, - _ => { - let tmp = disk_info.old_disk_bytes.borrow(); - return DiskUsage { - total_read_bytes: tmp.read_bytes, - read_bytes: 0, - total_written_bytes: tmp.written_bytes, - written_bytes: 0, - }; - } - }; - let (read_bytes, written_bytes, old_read_bytes, old_written_bytes) = { - let mut tmp = disk_info.old_disk_bytes.borrow_mut(); - let read_bytes = report.get_bytes_read_count().ok().map(|x| x as u64).unwrap_or(tmp.read_bytes); - let written_bytes = report.get_bytes_written_count().ok().map(|x| x as u64).unwrap_or(tmp.written_bytes); - let old_read_bytes = tmp.read_bytes; - let old_written_bytes = tmp.written_bytes; - tmp.read_bytes = read_bytes; - tmp.written_bytes = written_bytes; - (read_bytes, written_bytes, old_read_bytes, old_written_bytes) - }; - DiskUsage { - total_read_bytes: read_bytes, - read_bytes: read_bytes - old_read_bytes, - total_written_bytes: written_bytes, - written_bytes: written_bytes - old_written_bytes, - } - } else { - DiskUsage::default() + DiskUsage { + written_bytes: self.written_bytes - self.old_written_bytes, + total_written_bytes: self.written_bytes, + read_bytes: self.read_bytes - self.old_read_bytes, + total_read_bytes: self.read_bytes, } } } @@ -498,7 +439,7 @@ fn get_cmd_line(handle: HANDLE) -> Vec { use winapi::um::memoryapi::ReadProcessMemory; unsafe { - let mut pinfo = std::mem::MaybeUninit::::uninit(); + let mut pinfo = MaybeUninit::::uninit(); if NtQueryInformationProcess( handle, 0, // ProcessBasicInformation @@ -512,7 +453,7 @@ fn get_cmd_line(handle: HANDLE) -> Vec { let pinfo = pinfo.assume_init(); let ppeb: PPEB = pinfo.PebBaseAddress; - let mut peb_copy = std::mem::MaybeUninit::::uninit(); + let mut peb_copy = MaybeUninit::::uninit(); if ReadProcessMemory( handle, ppeb as *mut _, @@ -526,8 +467,7 @@ fn get_cmd_line(handle: HANDLE) -> Vec { let peb_copy = peb_copy.assume_init(); let proc_param = peb_copy.ProcessParameters; - let mut rtl_proc_param_copy = - std::mem::MaybeUninit::::uninit(); + let mut rtl_proc_param_copy = MaybeUninit::::uninit(); if ReadProcessMemory( handle, proc_param as *mut PRTL_USER_PROCESS_PARAMETERS as *mut _, @@ -716,6 +656,21 @@ pub fn get_handle(p: &Process) -> HANDLE { pub fn update_proc_info(p: &mut Process) { update_memory(p); + update_disk_usage(p); +} + +pub fn update_disk_usage(p: &mut Process) { + let mut counters = MaybeUninit::::uninit(); + let ret = unsafe { GetProcessIoCounters(*p.handle, counters.as_mut_ptr()) }; + if ret == 0 { + sysinfo_debug!("GetProcessIoCounters call failed on process {}", p.pid()); + } else { + let counters = unsafe { counters.assume_init() }; + p.old_read_bytes = p.read_bytes; + p.old_written_bytes = p.written_bytes; + p.read_bytes = counters.ReadTransferCount; + p.written_bytes = counters.WriteTransferCount; + } } pub fn update_memory(p: &mut Process) { diff --git a/src/windows/system.rs b/src/windows/system.rs index 17ab870ff..9070f9e1f 100644 --- a/src/windows/system.rs +++ b/src/windows/system.rs @@ -23,7 +23,7 @@ use SystemExt; use User; use windows::process::{ - compute_cpu_usage, get_handle, get_system_computation_time, update_proc_info, + compute_cpu_usage, get_handle, get_system_computation_time, update_disk_usage, update_proc_info, Process, }; use windows::tools::*; @@ -39,8 +39,6 @@ use winapi::um::processthreadsapi::GetExitCodeProcess; use winapi::um::sysinfoapi::{GetTickCount64, GlobalMemoryStatusEx, MEMORYSTATUSEX}; use winapi::um::winnt::HANDLE; use rayon::prelude::*; -use winrt::windows::system::{AppDiagnosticInfo, DiagnosticAccessStatus}; -use winrt::{RtAsyncOperation, RtActivatable}; /// Struct containing the system's information. pub struct System { @@ -75,79 +73,9 @@ unsafe fn boot_time() -> u64 { } } -// To be removed once winrt PR is merged! -#[derive(Clone, Copy, Debug, PartialEq)] -pub(crate) enum RegistrationStatus { - Ok, - NotRegistered, - Error(u32), -} - -// To be removed once winrt PR is merged! -pub(crate) fn can_be_registered>() -> RegistrationStatus { - use std::ptr; - use winapi::shared::ntdef::VOID; - use winapi::shared::winerror::{S_OK, CO_E_NOTINITIALIZED, REGDB_E_CLASSNOTREG}; - use winapi::um::combaseapi::CoIncrementMTAUsage; - use winapi::winrt::roapi::RoGetActivationFactory; - use winrt::{ComIid, HStringReference, RtType}; - - let mut res: ::Abi = unsafe { - ::uninitialized() - }; - let class_id = unsafe { HStringReference::from_utf16_unchecked(T::name()) }; - let mut hr = unsafe { - RoGetActivationFactory( - class_id.get(), - ::iid().as_ref(), - &mut res as *mut *mut _ as *mut *mut VOID, - ) - }; - if hr == CO_E_NOTINITIALIZED { - let mut cookie = ptr::null_mut(); - unsafe { CoIncrementMTAUsage(&mut cookie); } - hr = unsafe { - RoGetActivationFactory( - class_id.get(), - ::iid().as_ref(), - &mut res as *mut *mut _ as *mut *mut VOID, - ) - }; - } - if hr == S_OK { - RegistrationStatus::Ok - } else if hr == REGDB_E_CLASSNOTREG { - RegistrationStatus::NotRegistered - } else { - RegistrationStatus::Error(hr as u32) - } -} - impl SystemExt for System { #[allow(non_snake_case)] fn new_with_specifics(refreshes: RefreshKind) -> System { - match can_be_registered::() { - RegistrationStatus::Ok => { - match AppDiagnosticInfo::request_access_async() { - Ok(x) => { - match x.blocking_get() { - Ok(DiagnosticAccessStatus::Unspecified) => { - sysinfo_debug!("app diagnostic access refused: Unspecified"); - } - Ok(DiagnosticAccessStatus::Denied) => { - sysinfo_debug!("app diagnostic access refused: Denied"); - } - Ok(_) => {} - Err(_e) => { - sysinfo_debug!("failed to get access request status: {:?}", _e); - } - } - } - Err(_e) => sysinfo_debug!("failed to request app diagnostic access: {:?}", _e), - } - } - _x => sysinfo_debug!("Cannot register AppDiagnosticInfo: {:?}", _x), - } let (processors, vendor_id, brand) = init_processors(); let mut s = System { process_list: HashMap::with_capacity(500), @@ -252,6 +180,7 @@ impl SystemExt for System { } else if let Some(mut p) = Process::new_from_pid(pid) { let system_time = get_system_computation_time(); compute_cpu_usage(&mut p, self.processors.len() as u64, system_time); + update_disk_usage(&mut p); self.process_list.insert(pid, p); true } else { @@ -320,6 +249,7 @@ impl SystemExt for System { proc_.memory = (pi.WorkingSetSize as u64) >> 10u64; proc_.virtual_memory = (pi.VirtualSize as u64) >> 10u64; compute_cpu_usage(proc_, nb_processors, system_time); + update_disk_usage(proc_); proc_.updated = true; return None; } @@ -336,6 +266,7 @@ impl SystemExt for System { name, ); compute_cpu_usage(&mut p, nb_processors, system_time); + update_disk_usage(&mut p); Some(p) }) .collect::>(); diff --git a/tests/process.rs b/tests/process.rs index 89fdef952..b5b2dff2a 100644 --- a/tests/process.rs +++ b/tests/process.rs @@ -43,20 +43,32 @@ fn test_get_cmd_line() { .spawn() .unwrap(); let mut s = sysinfo::System::new(); + assert!(s.get_processes().len() == 0); s.refresh_processes(); - let process = s.get_process(p.id() as sysinfo::Pid).unwrap(); - assert_eq!(process.cmd(), &["timeout", "/t", "3"]); + assert!(s.get_processes().len() > 0); + if let Some(process) = s.get_process(p.id() as sysinfo::Pid) { + assert_eq!(process.cmd(), &["timeout", "/t", "3"]); + } else { + // We're very likely on a "linux-like" shell so let's try some unix command... + unix_like_cmd(); + } } #[test] #[cfg(not(windows))] fn test_get_cmd_line() { + unix_like_cmd(); +} + +fn unix_like_cmd() { let p = std::process::Command::new("sleep") .arg("3") .spawn() .unwrap(); let mut s = sysinfo::System::new(); + assert!(s.get_processes().len() == 0); s.refresh_processes(); + assert!(s.get_processes().len() > 0); let process = s.get_process(p.id() as sysinfo::Pid).unwrap(); assert_eq!(process.cmd(), &["sleep", "3"]); } @@ -74,10 +86,21 @@ fn test_process_disk_usage() { } fs::remove_file("test.txt").ok(); let mut system = sysinfo::System::new(); + assert!(system.get_processes().len() == 0); system.refresh_processes(); + assert!(system.get_processes().len() > 0); let p = system .get_process(get_current_pid().expect("Failed retrieving current pid.")) .expect("failed to get process"); - assert!(p.get_disk_usage().total_written_bytes > 0); + assert!( + p.get_disk_usage().total_written_bytes > 0, + "found {} total written bytes...", + p.get_disk_usage().total_written_bytes + ); + assert!( + p.get_disk_usage().written_bytes > 0, + "found {} written bytes...", + p.get_disk_usage().written_bytes + ); }