Skip to content

Commit

Permalink
Merge pull request #1264 from GuillaumeGomez/global-cpu-info
Browse files Browse the repository at this point in the history
Only store CPU usage for global CPU
  • Loading branch information
GuillaumeGomez committed Apr 28, 2024
2 parents 1e4c985 + 8fd58b8 commit 550ce2c
Show file tree
Hide file tree
Showing 16 changed files with 177 additions and 190 deletions.
2 changes: 1 addition & 1 deletion examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ fn interpret_input(
writeln!(
&mut io::stdout(),
"total CPU usage: {}%",
sys.global_cpu_info().cpu_usage()
sys.global_cpu_usage(),
);
for cpu in sys.cpus() {
writeln!(&mut io::stdout(), "{cpu:?}");
Expand Down
17 changes: 4 additions & 13 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,30 +514,21 @@ impl System {
.filter(move |val: &&Process| val.name() == name)
}

/// Returns "global" CPUs information (aka the addition of all the CPUs).
/// Returns "global" CPUs usage (aka the addition of all the CPUs).
///
/// To have up-to-date information, you need to call [`System::refresh_cpu_specifics`] or
/// [`System::refresh_specifics`] with `cpu` enabled.
///
/// **⚠️ Important ⚠️**
///
/// Information like [`Cpu::brand`], [`Cpu::vendor_id`] or [`Cpu::frequency`]
/// are not set on the "global" CPU.
///
/// ```no_run
/// use sysinfo::{CpuRefreshKind, RefreshKind, System};
///
/// let s = System::new_with_specifics(
/// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
/// );
/// println!("{}%", s.global_cpu_info().cpu_usage());
/// println!("{}%", s.global_cpu_usage());
/// ```
///
/// [`Cpu::brand`]: crate::Cpu::brand
/// [`Cpu::vendor_id`]: crate::Cpu::vendor_id
/// [`Cpu::frequency`]: crate::Cpu::frequency
pub fn global_cpu_info(&self) -> &Cpu {
self.inner.global_cpu_info()
pub fn global_cpu_usage(&self) -> f32 {
self.inner.global_cpu_usage()
}

/// Returns the list of the CPUs.
Expand Down
2 changes: 1 addition & 1 deletion src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl fmt::Debug for Cpu {
impl fmt::Debug for System {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("System")
.field("global CPU usage", &self.global_cpu_info().cpu_usage())
.field("global CPU usage", &self.global_cpu_usage())
.field("load average", &Self::load_average())
.field("total memory", &self.total_memory())
.field("free memory", &self.free_memory())
Expand Down
9 changes: 0 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,15 +493,6 @@ mod test {
}
}

// Ensure that the global CPU name is always empty.
#[test]
fn check_global_cpu_name() {
let mut s = System::new();
assert_eq!(s.global_cpu_info().name(), "");
s.refresh_cpu_all();
assert_eq!(s.global_cpu_info().name(), "");
}

// In case `Process::updated` is misused, `System::refresh_processes` might remove them
// so this test ensures that it doesn't happen.
#[test]
Expand Down
2 changes: 1 addition & 1 deletion src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl serde::Serialize for crate::System {
// `19` corresponds to the number of fields.
let mut state = serializer.serialize_struct("System", 19)?;

state.serialize_field("global_cpu_info", &self.global_cpu_info())?;
state.serialize_field("global_cpu_usage", &self.global_cpu_usage())?;
state.serialize_field("cpus", &self.cpus())?;

state.serialize_field("physical_core_count", &self.physical_core_count())?;
Expand Down
71 changes: 44 additions & 27 deletions src/unix/apple/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::sync::Arc;
use std::time::Instant;

pub(crate) struct CpusWrapper {
pub(crate) global_cpu: Cpu,
pub(crate) global_cpu: CpuUsage,
pub(crate) cpus: Vec<Cpu>,
pub(crate) got_cpu_frequency: bool,
/// This field is needed to prevent updating when not enough time passed since last update.
Expand All @@ -20,15 +20,7 @@ pub(crate) struct CpusWrapper {
impl CpusWrapper {
pub(crate) fn new() -> Self {
Self {
global_cpu: Cpu {
inner: CpuInner::new(
String::new(),
Arc::new(CpuData::new(std::ptr::null_mut(), 0)),
0,
String::new(),
String::new(),
),
},
global_cpu: CpuUsage::new(),
cpus: Vec::new(),
got_cpu_frequency: false,
last_update: None,
Expand Down Expand Up @@ -115,13 +107,36 @@ impl Drop for CpuData {
}
}

pub(crate) struct CpuUsage {
percent: f32,
data: Arc<CpuData>,
// Cannot be frequency for each CPU apparently so we store it in the CPU usage...
frequency: u64,
}

impl CpuUsage {
pub(crate) fn new() -> Self {
Self {
percent: 0.,
data: Arc::new(CpuData::new(std::ptr::null_mut(), 0)),
frequency: 0,
}
}

pub(crate) fn percent(&self) -> f32 {
self.percent
}

pub(crate) fn set_cpu_usage(&mut self, value: f32) {
self.percent = value;
}
}

pub(crate) struct CpuInner {
name: String,
cpu_usage: f32,
cpu_data: Arc<CpuData>,
frequency: u64,
vendor_id: String,
brand: String,
usage: CpuUsage,
}

impl CpuInner {
Expand All @@ -134,41 +149,43 @@ impl CpuInner {
) -> Self {
Self {
name,
cpu_usage: 0f32,
cpu_data,
frequency,
usage: CpuUsage {
percent: 0.,
data: cpu_data,
frequency,
},
vendor_id,
brand,
}
}

pub(crate) fn set_cpu_usage(&mut self, cpu_usage: f32) {
self.cpu_usage = cpu_usage;
self.usage.set_cpu_usage(cpu_usage);
}

pub(crate) fn update(&mut self, cpu_usage: f32, cpu_data: Arc<CpuData>) {
self.cpu_usage = cpu_usage;
self.cpu_data = cpu_data;
self.usage.percent = cpu_usage;
self.usage.data = cpu_data;
}

pub(crate) fn data(&self) -> Arc<CpuData> {
Arc::clone(&self.cpu_data)
Arc::clone(&self.usage.data)
}

pub(crate) fn set_frequency(&mut self, frequency: u64) {
self.frequency = frequency;
self.usage.frequency = frequency;
}

pub(crate) fn cpu_usage(&self) -> f32 {
self.cpu_usage
self.usage.percent()
}

pub(crate) fn name(&self) -> &str {
&self.name
}

pub(crate) fn frequency(&self) -> u64 {
self.frequency
self.usage.frequency
}

pub(crate) fn vendor_id(&self) -> &str {
Expand Down Expand Up @@ -267,7 +284,7 @@ pub(crate) fn compute_usage_of_cpu(proc_: &Cpu, cpu_info: *mut i32, offset: isiz

pub(crate) fn update_cpu_usage<F: FnOnce(Arc<CpuData>, *mut i32) -> (f32, usize)>(
port: libc::mach_port_t,
global_cpu: &mut Cpu,
global_cpu: &mut CpuUsage,
f: F,
) {
let mut num_cpu_u = 0u32;
Expand All @@ -289,14 +306,14 @@ pub(crate) fn update_cpu_usage<F: FnOnce(Arc<CpuData>, *mut i32) -> (f32, usize)
f(Arc::new(CpuData::new(cpu_info, num_cpu_info)), cpu_info);
total_cpu_usage = total_percentage / len as f32;
}
global_cpu.inner.set_cpu_usage(total_cpu_usage);
global_cpu.set_cpu_usage(total_cpu_usage);
}
}

pub(crate) fn init_cpus(
port: libc::mach_port_t,
cpus: &mut Vec<Cpu>,
global_cpu: &mut Cpu,
global_cpu: &mut CpuUsage,
refresh_kind: CpuRefreshKind,
) {
let mut num_cpu = 0;
Expand All @@ -306,7 +323,7 @@ pub(crate) fn init_cpus(
let frequency = if refresh_kind.frequency() {
unsafe { get_cpu_frequency() }
} else {
global_cpu.frequency()
global_cpu.frequency
};

unsafe {
Expand Down
4 changes: 2 additions & 2 deletions src/unix/apple/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ impl SystemInner {
self.process_list.get(&pid)
}

pub(crate) fn global_cpu_info(&self) -> &Cpu {
&self.cpus.global_cpu
pub(crate) fn global_cpu_usage(&self) -> f32 {
self.cpus.global_cpu.percent()
}

pub(crate) fn cpus(&self) -> &[Cpu] {
Expand Down
22 changes: 8 additions & 14 deletions src/unix/freebsd/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub(crate) unsafe fn get_nb_cpus() -> usize {
}

pub(crate) struct CpusWrapper {
pub(crate) global_cpu: Cpu,
pub(crate) global_cpu_usage: f32,
pub(crate) cpus: Vec<Cpu>,
got_cpu_frequency: bool,
mib_cp_time: [c_int; 2],
Expand All @@ -46,9 +46,7 @@ impl CpusWrapper {
init_mib(b"kern.cp_time\0", &mut mib_cp_time);
init_mib(b"kern.cp_times\0", &mut mib_cp_times);
Self {
global_cpu: Cpu {
inner: CpuInner::new(String::new(), String::new(), 0),
},
global_cpu_usage: 0.,
cpus: Vec::with_capacity(nb_cpus),
got_cpu_frequency: false,
mib_cp_time,
Expand Down Expand Up @@ -98,7 +96,7 @@ impl CpusWrapper {
get_sys_value_array(&self.mib_cp_times, self.cp_times.get_mut());
}

fn fill_cpu(proc_: &mut Cpu, new_cp_time: &[c_ulong], old_cp_time: &[c_ulong]) {
fn compute_cpu_usage(new_cp_time: &[c_ulong], old_cp_time: &[c_ulong]) -> f32 {
let mut total_new: u64 = 0;
let mut total_old: u64 = 0;
let mut cp_diff: c_ulong = 0;
Expand All @@ -115,23 +113,19 @@ impl CpusWrapper {

let total_diff = total_new.saturating_sub(total_old);
if total_diff < 1 {
proc_.inner.cpu_usage = 0.;
0.
} else {
proc_.inner.cpu_usage = cp_diff as f32 / total_diff as f32 * 100.;
cp_diff as f32 / total_diff as f32 * 100.
}
}

fill_cpu(
&mut self.global_cpu,
self.cp_time.get_new(),
self.cp_time.get_old(),
);
self.global_cpu_usage = compute_cpu_usage(self.cp_time.get_new(), self.cp_time.get_old());
let old_cp_times = self.cp_times.get_old();
let new_cp_times = self.cp_times.get_new();
for (pos, proc_) in self.cpus.iter_mut().enumerate() {
for (pos, cpu) in self.cpus.iter_mut().enumerate() {
let index = pos * libc::CPUSTATES as usize;

fill_cpu(proc_, &new_cp_times[index..], &old_cp_times[index..]);
cpu.inner.cpu_usage = compute_cpu_usage(&new_cp_times[index..], &old_cp_times[index..]);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/unix/freebsd/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ impl SystemInner {
self.process_list.get(&pid)
}

pub(crate) fn global_cpu_info(&self) -> &Cpu {
&self.cpus.global_cpu
pub(crate) fn global_cpu_usage(&self) -> f32 {
self.cpus.global_cpu_usage
}

pub(crate) fn cpus(&self) -> &[Cpu] {
Expand Down

0 comments on commit 550ce2c

Please sign in to comment.