mirror of
https://github.com/Llewellynvdm/starship.git
synced 2024-11-24 21:57:41 +00:00
refactor(memory_usage): replace sys-info
with systemstat
(#4028)
This commit is contained in:
parent
89b12cef01
commit
2039931d85
36
Cargo.lock
generated
36
Cargo.lock
generated
@ -210,15 +210,6 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byte-unit"
|
|
||||||
version = "4.0.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "95ebf10dda65f19ff0f42ea15572a359ed60d7fc74fdc984d90310937be0014b"
|
|
||||||
dependencies = [
|
|
||||||
"utf8-width",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
@ -231,6 +222,12 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytesize"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cache-padded"
|
name = "cache-padded"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -2039,7 +2036,6 @@ name = "starship"
|
|||||||
version = "1.7.1"
|
version = "1.7.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"byte-unit",
|
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
@ -2077,7 +2073,7 @@ dependencies = [
|
|||||||
"shell-words",
|
"shell-words",
|
||||||
"starship-battery",
|
"starship-battery",
|
||||||
"strsim",
|
"strsim",
|
||||||
"sys-info",
|
"systemstat",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"terminal_size",
|
"terminal_size",
|
||||||
"toml",
|
"toml",
|
||||||
@ -2154,13 +2150,17 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sys-info"
|
name = "systemstat"
|
||||||
version = "0.9.1"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c"
|
checksum = "5f5dc96f7634f46ac7e485b8c051f5b89ec8ee5cc023236dd12fe4ae2fb52f80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"bytesize",
|
||||||
|
"chrono",
|
||||||
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
"nom 7.1.1",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2444,12 +2444,6 @@ version = "2.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68b90931029ab9b034b300b797048cf23723400aa757e8a2bfb9d748102f9821"
|
checksum = "68b90931029ab9b034b300b797048cf23723400aa757e8a2bfb9d748102f9821"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "utf8-width"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -36,7 +36,6 @@ notify = ["notify-rust"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ansi_term = "0.12.1"
|
ansi_term = "0.12.1"
|
||||||
byte-unit = "4.0.14"
|
|
||||||
chrono = "0.4.19"
|
chrono = "0.4.19"
|
||||||
clap = { version = "3.1.18", features = ["derive", "cargo", "unicode"] }
|
clap = { version = "3.1.18", features = ["derive", "cargo", "unicode"] }
|
||||||
clap_complete = "3.1.4"
|
clap_complete = "3.1.4"
|
||||||
@ -70,7 +69,7 @@ shadow-rs = "0.11.0"
|
|||||||
# see: https://github.com/svartalf/rust-battery/issues/33
|
# see: https://github.com/svartalf/rust-battery/issues/33
|
||||||
starship-battery = { version = "0.7.9", optional = true }
|
starship-battery = { version = "0.7.9", optional = true }
|
||||||
strsim = "0.10.0"
|
strsim = "0.10.0"
|
||||||
sys-info = "0.9.1"
|
systemstat = "=0.1.11"
|
||||||
terminal_size = "0.1.17"
|
terminal_size = "0.1.17"
|
||||||
toml = { version = "0.5.9", features = ["preserve_order"] }
|
toml = { version = "0.5.9", features = ["preserve_order"] }
|
||||||
toml_edit = "0.14.4"
|
toml_edit = "0.14.4"
|
||||||
|
@ -1,23 +1,44 @@
|
|||||||
use byte_unit::{Byte, ByteUnit};
|
use systemstat::{
|
||||||
|
data::{saturating_sub_bytes, ByteSize},
|
||||||
|
Platform, System,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{Context, Module, ModuleConfig};
|
use super::{Context, Module, ModuleConfig};
|
||||||
|
|
||||||
use crate::configs::memory_usage::MemoryConfig;
|
use crate::configs::memory_usage::MemoryConfig;
|
||||||
use crate::formatter::StringFormatter;
|
use crate::formatter::StringFormatter;
|
||||||
|
|
||||||
fn format_kib(n_kib: u64) -> String {
|
// Display a `ByteSize` in a human readable format.
|
||||||
let byte = Byte::from_unit(n_kib as f64, ByteUnit::KiB).unwrap_or_else(|_| Byte::from_bytes(0));
|
fn display_bs(bs: ByteSize) -> String {
|
||||||
let mut display_bytes = byte.get_appropriate_unit(true).format(0);
|
let mut display_bytes = bs.to_string_as(true);
|
||||||
display_bytes.retain(|c| c != ' ');
|
let mut keep = true;
|
||||||
|
// Skip decimals and the space before the byte unit.
|
||||||
|
display_bytes.retain(|c| match c {
|
||||||
|
' ' => {
|
||||||
|
keep = true;
|
||||||
|
false
|
||||||
|
}
|
||||||
|
'.' => {
|
||||||
|
keep = false;
|
||||||
|
false
|
||||||
|
}
|
||||||
|
_ => keep,
|
||||||
|
});
|
||||||
display_bytes
|
display_bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_pct(pct_number: f64) -> String {
|
// Calculate the memory usage from total and free memory
|
||||||
format!("{:.0}%", pct_number)
|
fn pct(total: ByteSize, free: ByteSize) -> f64 {
|
||||||
|
100.0 * saturating_sub_bytes(total, free).0 as f64 / total.0 as f64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_usage_total(usage: u64, total: u64) -> String {
|
// Print usage string used/total
|
||||||
format!("{}/{}", format_kib(usage), format_kib(total))
|
fn format_usage_total(total: ByteSize, free: ByteSize) -> String {
|
||||||
|
format!(
|
||||||
|
"{}/{}",
|
||||||
|
display_bs(saturating_sub_bytes(total, free)),
|
||||||
|
display_bs(total)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a module with system memory usage information
|
/// Creates a module with system memory usage information
|
||||||
@ -31,36 +52,37 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let system = match sys_info::mem_info() {
|
let system = System::new();
|
||||||
Ok(info) => info,
|
|
||||||
Err(err) => {
|
// `memory_and_swap` only works on platforms that have an implementation for swap memory
|
||||||
log::warn!("Unable to access memory usage information:\n{}", err);
|
// But getting both together is faster on some platforms (Windows/Linux)
|
||||||
|
let (memory, swap) = match system.memory_and_swap() {
|
||||||
|
// Ignore swap if total is 0
|
||||||
|
Ok((mem, swap)) if swap.total.0 > 0 => (mem, Some(swap)),
|
||||||
|
Ok((mem, _)) => (mem, None),
|
||||||
|
Err(e) => {
|
||||||
|
log::debug!(
|
||||||
|
"Failed to retrieve both memory and swap, falling back to memory only: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
let mem = match system.memory() {
|
||||||
|
Ok(mem) => mem,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Failed to retrieve memory: {}", e);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// avail includes reclaimable memory, but isn't supported on all platforms
|
(mem, None)
|
||||||
let avail_memory_kib = match system.avail {
|
}
|
||||||
0 => system.free,
|
|
||||||
_ => system.avail,
|
|
||||||
};
|
};
|
||||||
let used_memory_kib = system.total.saturating_sub(avail_memory_kib);
|
|
||||||
let total_memory_kib = system.total;
|
|
||||||
let ram_used = (used_memory_kib as f64 / total_memory_kib as f64) * 100.;
|
|
||||||
let ram_pct = format_pct(ram_used);
|
|
||||||
|
|
||||||
let threshold = config.threshold;
|
let used_pct = pct(memory.total, memory.free);
|
||||||
if ram_used.round() < threshold as f64 {
|
|
||||||
|
if (used_pct.round() as i64) < config.threshold {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ram = format_usage_total(used_memory_kib, total_memory_kib);
|
|
||||||
let total_swap_kib = system.swap_total;
|
|
||||||
let used_swap_kib = system.swap_total.saturating_sub(system.swap_free);
|
|
||||||
let percent_swap_used = (used_swap_kib as f64 / total_swap_kib as f64) * 100.;
|
|
||||||
let swap_pct = format_pct(percent_swap_used);
|
|
||||||
let swap = format_usage_total(used_swap_kib, total_swap_kib);
|
|
||||||
|
|
||||||
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
||||||
formatter
|
formatter
|
||||||
.map_meta(|var, _| match var {
|
.map_meta(|var, _| match var {
|
||||||
@ -72,11 +94,16 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.map(|variable| match variable {
|
.map(|variable| match variable {
|
||||||
"ram" => Some(Ok(&ram)),
|
"ram" => Some(Ok(format_usage_total(memory.total, memory.free))),
|
||||||
"ram_pct" => Some(Ok(&ram_pct)),
|
"ram_pct" => Some(Ok(format!("{:.0}%", used_pct))),
|
||||||
// swap only shown if there is swap on the system
|
"swap" => Some(Ok(format_usage_total(
|
||||||
"swap" if total_swap_kib > 0 => Some(Ok(&swap)),
|
swap.as_ref()?.total,
|
||||||
"swap_pct" if total_swap_kib > 0 => Some(Ok(&swap_pct)),
|
swap.as_ref()?.free,
|
||||||
|
))),
|
||||||
|
"swap_pct" => Some(Ok(format!(
|
||||||
|
"{:.0}%",
|
||||||
|
pct(swap.as_ref()?.total, swap.as_ref()?.free)
|
||||||
|
))),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.parse(None, Some(context))
|
.parse(None, Some(context))
|
||||||
@ -92,3 +119,71 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
|||||||
|
|
||||||
Some(module)
|
Some(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate::test::ModuleRenderer;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_format_usage_total() {
|
||||||
|
assert_eq!(
|
||||||
|
format_usage_total(ByteSize(1024 * 1024 * 1024), ByteSize(1024 * 1024 * 1024)),
|
||||||
|
"0B/1GiB"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
format_usage_total(
|
||||||
|
ByteSize(1024 * 1024 * 1024),
|
||||||
|
ByteSize(1024 * 1024 * 1024 / 2)
|
||||||
|
),
|
||||||
|
"512MiB/1GiB"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
format_usage_total(ByteSize(1024 * 1024 * 1024), ByteSize(0)),
|
||||||
|
"1GiB/1GiB"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pct() {
|
||||||
|
assert_eq!(
|
||||||
|
pct(ByteSize(1024 * 1024 * 1024), ByteSize(1024 * 1024 * 1024)),
|
||||||
|
0.0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
pct(
|
||||||
|
ByteSize(1024 * 1024 * 1024),
|
||||||
|
ByteSize(1024 * 1024 * 1024 / 2)
|
||||||
|
),
|
||||||
|
50.0
|
||||||
|
);
|
||||||
|
assert_eq!(pct(ByteSize(1024 * 1024 * 1024), ByteSize(0)), 100.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn zero_threshold() {
|
||||||
|
let output = ModuleRenderer::new("memory_usage")
|
||||||
|
.config(toml::toml! {
|
||||||
|
[memory_usage]
|
||||||
|
disabled = false
|
||||||
|
threshold = 0
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert!(output.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn impossible_threshold() {
|
||||||
|
let output = ModuleRenderer::new("memory_usage")
|
||||||
|
.config(toml::toml! {
|
||||||
|
[memory_usage]
|
||||||
|
disabled = false
|
||||||
|
threshold = 9999
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assert!(output.is_none())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user