Skip to content

Commit

Permalink
Replace winrt with GetProcessIoCounters
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Apr 7, 2020
1 parent bf16c48 commit 137cd5f
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 180 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,21 +131,21 @@ test bench_refresh_users_list ... bench: 2,095,043 ns/iter (+/- 648,385)
<details>

```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)
```
</details>

Expand Down
1 change: 0 additions & 1 deletion src/sysinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
127 changes: 41 additions & 86 deletions src/windows/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)]
Expand Down Expand Up @@ -83,20 +81,6 @@ impl<T: Clone> Deref for PtrWrapper<T> {
unsafe impl<T: Clone> Send for PtrWrapper<T> {}
unsafe impl<T: Clone> Sync for PtrWrapper<T> {}

#[derive(Default)]
struct DiskBytes {
written_bytes: u64,
read_bytes: u64,
}

struct DiskInfo {
diag_info: PtrWrapper<ComPtr<ProcessDiagnosticInfo>>,
old_disk_bytes: RefCell<DiskBytes>,
}

unsafe impl Send for DiskInfo {}
unsafe impl Sync for DiskInfo {}

/// Struct containing a process' information.
pub struct Process {
name: String,
Expand All @@ -117,7 +101,10 @@ pub struct Process {
start_time: u64,
cpu_usage: f32,
pub(crate) updated: bool,
disk_info: Option<DiskInfo>,
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 {
Expand Down Expand Up @@ -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<DiskInfo> {
use super::system::{can_be_registered, RegistrationStatus};

match can_be_registered::<ProcessDiagnosticInfo>() {
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<Process> {
Expand Down Expand Up @@ -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 {
Expand All @@ -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,
}
}
}
Expand Down Expand Up @@ -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,
}
}
}
Expand Down Expand Up @@ -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,
}
}
}
Expand Down Expand Up @@ -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,
}
}
}
Expand Down Expand Up @@ -716,6 +657,20 @@ 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: IO_COUNTERS = unsafe { MaybeUninit::uninit().assume_init() };
let ret = unsafe { GetProcessIoCounters(*p.handle, &mut counters) };
if ret == 0 {
sysinfo_debug!("GetProcessIoCounters call failed on process {}", p.pid());
} else {
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) {
Expand Down
77 changes: 4 additions & 73 deletions src/windows/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -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 {
Expand Down Expand Up @@ -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<T: RtActivatable<T>>() -> 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: <T as RtType>::Abi = unsafe {
<T as RtType>::uninitialized()
};
let class_id = unsafe { HStringReference::from_utf16_unchecked(T::name()) };
let mut hr = unsafe {
RoGetActivationFactory(
class_id.get(),
<T as ComIid>::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(),
<T as ComIid>::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::<AppDiagnosticInfo>() {
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),
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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::<Vec<_>>();
Expand Down
Loading

0 comments on commit 137cd5f

Please sign in to comment.