Skip to content

Commit

Permalink
Only store CPU usage for global CPU
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Apr 28, 2024
1 parent 8507baa commit 663c976
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 147 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
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 = fill_cpu(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 = fill_cpu(&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
138 changes: 75 additions & 63 deletions src/unix/linux/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ macro_rules! to_str {
}

pub(crate) struct CpusWrapper {
pub(crate) global_cpu: Cpu,
pub(crate) global_cpu: CpuUsage,
pub(crate) cpus: Vec<Cpu>,
/// Field set to `false` in `update_cpus` and to `true` in `refresh_processes_specifics`.
///
Expand All @@ -32,24 +32,7 @@ pub(crate) struct CpusWrapper {
impl CpusWrapper {
pub(crate) fn new() -> Self {
Self {
global_cpu: Cpu {
inner: CpuInner::new_with_values(
"",
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
String::new(),
String::new(),
),
},
global_cpu: CpuUsage::default(),
cpus: Vec::with_capacity(4),
need_cpus_update: true,
got_cpu_frequency: false,
Expand Down Expand Up @@ -103,7 +86,7 @@ impl CpusWrapper {
return;
}
let mut parts = line.split(|x| *x == b' ').filter(|s| !s.is_empty()).skip(1);
self.global_cpu.inner.set(
self.global_cpu.set(
parts.next().map(to_u64).unwrap_or(0),
parts.next().map(to_u64).unwrap_or(0),
parts.next().map(to_u64).unwrap_or(0),
Expand Down Expand Up @@ -200,10 +183,7 @@ impl CpusWrapper {
}

pub(crate) fn get_global_raw_times(&self) -> (u64, u64) {
(
self.global_cpu.inner.total_time,
self.global_cpu.inner.old_total_time,
)
(self.global_cpu.total_time, self.global_cpu.old_total_time)
}

pub(crate) fn len(&self) -> usize {
Expand All @@ -220,7 +200,7 @@ impl CpusWrapper {
}

/// Struct containing values to compute a CPU usage.
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Default)]
pub(crate) struct CpuValues {
user: u64,
nice: u64,
Expand All @@ -235,22 +215,6 @@ pub(crate) struct CpuValues {
}

impl CpuValues {
/// Creates a new instance of `CpuValues` with everything set to `0`.
pub fn new() -> CpuValues {
CpuValues {
user: 0,
nice: 0,
system: 0,
idle: 0,
iowait: 0,
irq: 0,
softirq: 0,
steal: 0,
guest: 0,
guest_nice: 0,
}
}

/// Sets the given argument to the corresponding fields.
pub fn set(
&mut self,
Expand Down Expand Up @@ -301,21 +265,17 @@ impl CpuValues {
}
}

pub(crate) struct CpuInner {
#[derive(Default)]
pub(crate) struct CpuUsage {
percent: f32,
old_values: CpuValues,
new_values: CpuValues,
pub(crate) name: String,
cpu_usage: f32,
total_time: u64,
old_total_time: u64,
pub(crate) frequency: u64,
pub(crate) vendor_id: String,
pub(crate) brand: String,
}

impl CpuInner {
impl CpuUsage {
pub(crate) fn new_with_values(
name: &str,
user: u64,
nice: u64,
system: u64,
Expand All @@ -326,24 +286,17 @@ impl CpuInner {
steal: u64,
guest: u64,
guest_nice: u64,
frequency: u64,
vendor_id: String,
brand: String,
) -> Self {
let mut new_values = CpuValues::new();
let mut new_values = CpuValues::default();
new_values.set(
user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice,
);
Self {
name: name.to_owned(),
old_values: CpuValues::new(),
old_values: CpuValues::default(),
new_values,
cpu_usage: 0f32,
percent: 0f32,
total_time: 0,
old_total_time: 0,
frequency,
vendor_id,
brand,
}
}

Expand Down Expand Up @@ -375,16 +328,75 @@ impl CpuInner {
);
self.total_time = self.new_values.total_time();
self.old_total_time = self.old_values.total_time();
self.cpu_usage = min!(self.new_values.work_time(), self.old_values.work_time(), 0.)
self.percent = min!(self.new_values.work_time(), self.old_values.work_time(), 0.)
/ min!(self.total_time, self.old_total_time, 1.)
* 100.;
if self.cpu_usage > 100. {
self.cpu_usage = 100.; // to prevent the percentage to go above 100%
if self.percent > 100. {
self.percent = 100.; // to prevent the percentage to go above 100%
}
}

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

pub(crate) struct CpuInner {
usage: CpuUsage,
pub(crate) name: String,
pub(crate) frequency: u64,
pub(crate) vendor_id: String,
pub(crate) brand: String,
}

impl CpuInner {
pub(crate) fn new_with_values(
name: &str,
user: u64,
nice: u64,
system: u64,
idle: u64,
iowait: u64,
irq: u64,
softirq: u64,
steal: u64,
guest: u64,
guest_nice: u64,
frequency: u64,
vendor_id: String,
brand: String,
) -> Self {
Self {
usage: CpuUsage::new_with_values(
user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice,
),
name: name.to_owned(),
frequency,
vendor_id,
brand,
}
}

pub(crate) fn set(
&mut self,
user: u64,
nice: u64,
system: u64,
idle: u64,
iowait: u64,
irq: u64,
softirq: u64,
steal: u64,
guest: u64,
guest_nice: u64,
) {
self.usage.set(
user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice,
);
}

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

pub(crate) fn name(&self) -> &str {
Expand Down
4 changes: 2 additions & 2 deletions src/unix/linux/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,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 663c976

Please sign in to comment.