Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add governor information #1057

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions examples/simple.rs
Expand Up @@ -232,6 +232,9 @@ fn interpret_input(input: &str, sys: &mut System) -> bool {
sys.global_cpu_info().frequency()
);
}
"governor" => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not displaying this information as part of the CPUs directly?

writeln!(&mut io::stdout(), "governor: {}", sys.cpus()[0].governor());
}
"vendor_id" => {
writeln!(
&mut io::stdout(),
Expand Down
6 changes: 5 additions & 1 deletion src/apple/cpu.rs
@@ -1,7 +1,7 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use crate::sys::utils::{get_sys_value, get_sys_value_by_name};
use crate::{CpuExt, CpuRefreshKind};
use crate::{CpuExt, CpuRefreshKind, GovernorKind};

use libc::{c_char, c_void, host_processor_info, mach_port_t, mach_task_self};
use std::mem;
Expand Down Expand Up @@ -170,6 +170,10 @@ impl CpuExt for Cpu {
fn brand(&self) -> &str {
&self.brand
}

fn governor(&self) -> GovernorKind {
GovernorKind::default()
}
}

pub(crate) unsafe fn get_cpu_frequency() -> u64 {
Expand Down
7 changes: 6 additions & 1 deletion src/apple/system.rs
Expand Up @@ -6,7 +6,8 @@ use crate::sys::process::*;
use crate::sys::utils::{get_sys_value, get_sys_value_by_name};

use crate::{
CpuRefreshKind, Disks, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind, SystemExt, User,
CpuRefreshKind, Disks, GovernorKind, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind,
SystemExt, User,
};

#[cfg(all(target_os = "macos", not(feature = "apple-sandbox")))]
Expand Down Expand Up @@ -346,6 +347,10 @@ impl SystemExt for System {
&self.cpus.global_cpu
}

fn governor(&self) -> GovernorKind {
GovernorKind::default()
}

fn cpus(&self) -> &[Cpu] {
&self.cpus.cpus
}
Expand Down
68 changes: 68 additions & 0 deletions src/common.rs
Expand Up @@ -462,6 +462,74 @@ impl RefreshKind {
impl_get_set!(RefreshKind, users_list, with_users_list, without_users_list);
}

/// Enum containing the different supported kinds CPUs governor.
///
/// This type is returned by `governor`.
///
/// ```no_run
/// use sysinfo::{System, SystemExt};
/// let s = System::new_all();
/// let governor = s.governor();
/// ```
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum GovernorKind {
/// CPU operating in the highest frequency within the borders
/// of scaling_min_freq and scaling_max_freq.
Performance,
/// CPU operating statically to the lowest frequency within
/// the borders of scaling_min_freq and scaling_max_freq.
Powersave,
/// Governor that allows the user, or any userspace program
/// running with UID "root", to set the CPU to a specific frequency
/// by making a sysfs file "scaling_setspeed" available in the CPU-device directory.
Userspace,
/// CPU operating in a frequency depending on the current system load.
Ondemand,
/// Close to Ondemand, differs in behaviour in that it gracefully increases and decreases the
/// CPU speed rather than jumping to max speed the moment there is any load on the CPU.
Conservative,
/// Aims at better integration with the Linux kernel scheduler.
Schedutil,
/// Unknown scheduler type
Unknown(String),
}

impl FromStr for GovernorKind {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s.to_lowercase().as_str() {
"performance" => GovernorKind::Performance,
"powersave" => GovernorKind::Powersave,
"userspace" => GovernorKind::Userspace,
"ondemand" => GovernorKind::Ondemand,
"conservative" => GovernorKind::Conservative,
"schedutil" => GovernorKind::Schedutil,
unknown => GovernorKind::Unknown(unknown.to_string()),
})
}
}

impl fmt::Display for GovernorKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
GovernorKind::Performance => "performance",
GovernorKind::Powersave => "powersave",
GovernorKind::Userspace => "userspace",
GovernorKind::Ondemand => "ondemand",
GovernorKind::Conservative => "conservative",
GovernorKind::Schedutil => "schedutil",
GovernorKind::Unknown(other) => other,
})
}
}

impl Default for GovernorKind {
fn default() -> Self {
GovernorKind::Unknown(Default::default())
}
}

/// Networks interfaces.
///
/// ```no_run
Expand Down
1 change: 1 addition & 0 deletions src/debug.rs
Expand Up @@ -13,6 +13,7 @@ impl fmt::Debug for Cpu {
.field("name", &self.name())
.field("CPU usage", &self.cpu_usage())
.field("frequency", &self.frequency())
.field("governor", &self.governor())
.field("vendor ID", &self.vendor_id())
.field("brand", &self.brand())
.finish()
Expand Down
6 changes: 5 additions & 1 deletion src/freebsd/cpu.rs
Expand Up @@ -3,7 +3,7 @@
use crate::sys::utils::{
get_sys_value_array, get_sys_value_by_name, get_sys_value_str_by_name, init_mib, VecSwitcher,
};
use crate::{CpuExt, CpuRefreshKind};
use crate::{CpuExt, CpuRefreshKind, GovernorKind};

use libc::{c_int, c_ulong};

Expand Down Expand Up @@ -171,6 +171,10 @@ impl CpuExt for Cpu {
fn brand(&self) -> &str {
""
}

fn governor(&self) -> GovernorKind {
GovernorKind::default()
}
}

pub(crate) fn physical_core_count() -> Option<usize> {
Expand Down
8 changes: 6 additions & 2 deletions src/freebsd/system.rs
Expand Up @@ -2,8 +2,8 @@

use crate::{
sys::{component::Component, Cpu, Process},
CpuRefreshKind, Disks, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind, SystemExt,
User,
CpuRefreshKind, Disks, GovernorKind, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind,
SystemExt, User,
};

use std::cell::UnsafeCell;
Expand Down Expand Up @@ -210,6 +210,10 @@ impl SystemExt for System {
&self.cpus.global_cpu
}

fn governor(&self) -> GovernorKind {
GovernorKind::default()
}

fn cpus(&self) -> &[Cpu] {
&self.cpus.cpus
}
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Expand Up @@ -80,9 +80,9 @@ cfg_if::cfg_if! {
}

pub use common::{
get_current_pid, CpuRefreshKind, DiskKind, DiskUsage, Disks, Gid, Group, LoadAvg, MacAddr,
Networks, NetworksIter, Pid, PidExt, ProcessRefreshKind, ProcessStatus, RefreshKind, Signal,
Uid,
get_current_pid, CpuRefreshKind, DiskKind, DiskUsage, Disks, Gid, GovernorKind, Group, LoadAvg,
MacAddr, Networks, NetworksIter, Pid, PidExt, ProcessRefreshKind, ProcessStatus, RefreshKind,
Signal, Uid,
};
pub use sys::{Component, Cpu, Disk, NetworkData, Process, System, User};
pub use traits::{
Expand Down
31 changes: 30 additions & 1 deletion src/linux/cpu.rs
Expand Up @@ -5,10 +5,11 @@
use std::collections::HashSet;
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::str::FromStr;
use std::time::Instant;

use crate::sys::utils::to_u64;
use crate::{CpuExt, CpuRefreshKind, SystemExt};
use crate::{CpuExt, CpuRefreshKind, GovernorKind, SystemExt};

macro_rules! to_str {
($e:expr) => {
Expand Down Expand Up @@ -47,6 +48,7 @@ impl CpusWrapper {
0,
String::new(),
String::new(),
GovernorKind::default(),
),
cpus: Vec::with_capacity(4),
need_cpus_update: true,
Expand Down Expand Up @@ -77,6 +79,7 @@ impl CpusWrapper {
} else {
(String::new(), String::new())
};
let governor = get_governor();

// If the last CPU usage update is too close (less than `MINIMUM_CPU_UPDATE_INTERVAL`),
// we don't want to update CPUs times.
Expand Down Expand Up @@ -142,6 +145,7 @@ impl CpusWrapper {
0,
vendor_id.clone(),
brand.clone(),
governor.clone().unwrap_or_default(),
));
} else {
parts.next(); // we don't want the name again
Expand Down Expand Up @@ -316,6 +320,7 @@ pub struct Cpu {
pub(crate) frequency: u64,
pub(crate) vendor_id: String,
pub(crate) brand: String,
pub(crate) governor: GovernorKind,
}

impl Cpu {
Expand All @@ -334,6 +339,7 @@ impl Cpu {
frequency: u64,
vendor_id: String,
brand: String,
governor: GovernorKind,
) -> Cpu {
let mut new_values = CpuValues::new();
new_values.set(
Expand All @@ -349,6 +355,7 @@ impl Cpu {
frequency,
vendor_id,
brand,
governor,
}
}

Expand Down Expand Up @@ -403,6 +410,10 @@ impl CpuExt for Cpu {
self.frequency
}

fn governor(&self) -> GovernorKind {
self.governor.clone()
}

fn vendor_id(&self) -> &str {
&self.vendor_id
}
Expand Down Expand Up @@ -447,6 +458,24 @@ pub(crate) fn get_cpu_frequency(cpu_core_index: usize) -> u64 {
.unwrap_or_default()
}

pub(crate) fn get_governor() -> Option<GovernorKind> {
let mut s = String::new();
// String should follow the pattern described in [governors.txt](https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt)
if File::open("/sys/devices/system/cpu/cpufreq/policy0/scaling_governor")
.and_then(|mut f| f.read_to_string(&mut s))
.is_ok()
{
let governor = s.trim().split('\n').next().unwrap_or_default();
if governor.is_empty() {
return None;
}

return Some(GovernorKind::from_str(governor).unwrap());
}

None
}

#[allow(unused_assignments)]
pub(crate) fn get_physical_core_count() -> Option<usize> {
let mut s = String::new();
Expand Down
7 changes: 6 additions & 1 deletion src/linux/system.rs
Expand Up @@ -5,7 +5,8 @@ use crate::sys::cpu::*;
use crate::sys::process::*;
use crate::sys::utils::{get_all_data, to_u64};
use crate::{
CpuRefreshKind, Disks, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind, SystemExt, User,
CpuRefreshKind, Disks, GovernorKind, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind,
SystemExt, User,
};

use libc::{self, c_char, c_int, sysconf, _SC_CLK_TCK, _SC_HOST_NAME_MAX, _SC_PAGESIZE};
Expand Down Expand Up @@ -402,6 +403,10 @@ impl SystemExt for System {
&self.cpus.global_cpu
}

fn governor(&self) -> GovernorKind {
get_governor().unwrap_or_default()
}

fn cpus(&self) -> &[Cpu] {
&self.cpus.cpus
}
Expand Down
30 changes: 28 additions & 2 deletions src/traits.rs
Expand Up @@ -5,8 +5,8 @@ use crate::{
sys::{Component, Cpu, Disk, Process},
};
use crate::{
CpuRefreshKind, DiskKind, DiskUsage, Disks, Group, LoadAvg, Networks, NetworksIter, Pid,
ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, User,
CpuRefreshKind, DiskKind, DiskUsage, Disks, GovernorKind, Group, LoadAvg, Networks,
NetworksIter, Pid, ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, User,
};

use std::collections::HashMap;
Expand Down Expand Up @@ -570,6 +570,20 @@ pub trait CpuExt: Debug {
/// }
/// ```
fn frequency(&self) -> u64;

/// Returns the CPU's governor.
///
/// ```no_run
/// use sysinfo::{CpuExt, GovernorKind, System, SystemExt, RefreshKind, CpuRefreshKind};
///
/// let s = System::new_with_specifics(
/// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
/// );
/// for cpu in s.cpus() {
/// println!("{}", cpu.governor());
/// }
/// ```
fn governor(&self) -> GovernorKind;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should return an Option in case this information hasn't been retrieved yet.

}

/// Contains all the methods of the [`System`][crate::System] type.
Expand Down Expand Up @@ -1069,6 +1083,18 @@ pub trait SystemExt: Sized + Debug + Default + Send + Sync {
/// ```
fn global_cpu_info(&self) -> &Cpu;

/// Returns the CPUs governor being used.
///
/// ```no_run
/// use sysinfo::{CpuRefreshKind, CpuExt, RefreshKind, System, SystemExt};
///
/// let s = System::new_with_specifics(
/// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
/// );
/// println!("{}%", s.global_cpu_info().cpu_usage());
/// ```
fn governor(&self) -> GovernorKind;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this from SystemExt, it should only be on CpuExt.


/// Returns the list of the CPUs.
///
/// By default, the list of CPUs is empty until you call [`SystemExt::refresh_cpu`] or
Expand Down
6 changes: 5 additions & 1 deletion src/unknown/cpu.rs
@@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use crate::CpuExt;
use crate::{CpuExt, GovernorKind};

#[doc = include_str!("../../md_doc/cpu.md")]
pub struct Cpu {}
Expand Down Expand Up @@ -31,4 +31,8 @@ impl CpuExt for Cpu {
fn brand(&self) -> &str {
""
}

fn governor(&self) -> GovernorKind {
GovernorKind::default()
}
}
8 changes: 6 additions & 2 deletions src/unknown/system.rs
Expand Up @@ -2,8 +2,8 @@

use crate::{
sys::{component::Component, Cpu, Process},
CpuRefreshKind, Disks, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind, SystemExt,
User,
CpuRefreshKind, Disks, GovernorKind, LoadAvg, Networks, Pid, ProcessRefreshKind, RefreshKind,
SystemExt, User,
};

use std::collections::HashMap;
Expand Down Expand Up @@ -74,6 +74,10 @@ impl SystemExt for System {
&self.global_cpu
}

fn governor(&self) -> GovernorKind {
GovernorKind::default()
}

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