mirror of
https://github.com/ClementTsang/bottom.git
synced 2026-05-03 13:30:44 +00:00
feature: free arc (#1812)
* feature: free arc * freebsd clippy no-default-features * add alias to free_arc * add get_threads to default config * clippy * code review: combine zfs feature and target_os build cfgs
This commit is contained in:
@@ -35,7 +35,7 @@ see information on these options by running `btm -h`, or run `btm --help` to dis
|
||||
| `--disable_advanced_kill` | Hides additional stopping options on Unix-like systems. |
|
||||
| `--get_threads` | Also gather process thread information. |
|
||||
| `-g, --group_processes` | Groups processes with the same name by default. No effect if `--tree` is set. |
|
||||
| `--hide_k_threads` | Hide kernel threads by default. |
|
||||
| `--hide_k_threads` | Hide kernel threads by default. |
|
||||
| `--process_memory_as_value` | Defaults to showing process memory usage by value. |
|
||||
| `--process_command` | Shows the full command name instead of the process name by default. |
|
||||
| `-R, --regex` | Enables regex by default while searching. |
|
||||
@@ -66,6 +66,7 @@ see information on these options by running `btm -h`, or run `btm --help` to dis
|
||||
| ---------------------------- | --------------------------------------------------------- |
|
||||
| `--memory_legend <POSITION>` | Where to place the legend for the memory chart widget. |
|
||||
| `--enable_cache_memory` | Enable collecting and displaying cache and buffer memory. |
|
||||
| `--free_arc` | Subtract freeable ARC from memory. |
|
||||
|
||||
## Network Options
|
||||
|
||||
|
||||
@@ -52,4 +52,5 @@ each time:
|
||||
| `network_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the network widget. |
|
||||
| `average_cpu_row` | Boolean | Moves the average CPU usage entry to its own row when using basic mode. |
|
||||
| `tree_collapse` | Boolean | Collapse process tree by default. |
|
||||
| `hide_k_threads` | Boolean | Hide kernel threads by default. |
|
||||
| `hide_k_threads` | Boolean | Hide kernel threads by default. |
|
||||
| `free_arc` | Boolean | Subtract freeable ARC from memory. |
|
||||
|
||||
@@ -115,6 +115,9 @@
|
||||
# Shows cache and buffer memory
|
||||
#enable_cache_memory = false
|
||||
|
||||
# Subtract freeable ARC from memory usage
|
||||
#free_arc = false
|
||||
|
||||
# How much data is stored at once in terms of time.
|
||||
#retention = "10m"
|
||||
|
||||
@@ -131,6 +134,9 @@
|
||||
# PID, Name, CPU%, Mem%, R/s, W/s, T.Read, T.Write, User, State, Time, GMem%, GPU%
|
||||
#columns = ["PID", "Name", "CPU%", "Mem%", "Virt", "R/s", "W/s", "T.Read", "T.Write", "User", "State", "GMem%", "GPU%"]
|
||||
|
||||
# Gather process child thread information
|
||||
#get_threads = false
|
||||
|
||||
|
||||
# CPU widget configuration
|
||||
#[cpu]
|
||||
|
||||
@@ -376,6 +376,12 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"free_arc": {
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"group_processes": {
|
||||
"type": [
|
||||
"boolean",
|
||||
|
||||
@@ -59,6 +59,8 @@ pub struct AppConfigFields {
|
||||
pub is_advanced_kill: bool,
|
||||
#[cfg(target_os = "linux")]
|
||||
pub hide_k_threads: bool,
|
||||
#[cfg(feature = "zfs")]
|
||||
pub free_arc: bool,
|
||||
pub memory_legend_position: Option<LegendPosition>,
|
||||
// TODO: Remove these, move network details state-side.
|
||||
pub network_unit_type: DataUnit,
|
||||
|
||||
+42
-5
@@ -184,6 +184,8 @@ pub struct DataCollector {
|
||||
gpu_pids: Option<Vec<HashMap<u32, (u64, u32)>>>,
|
||||
#[cfg(feature = "gpu")]
|
||||
gpus_total_mem: Option<u64>,
|
||||
#[cfg(feature = "zfs")]
|
||||
free_arc_mem: bool,
|
||||
}
|
||||
|
||||
const LESS_ROUTINE_TASK_TIME: Duration = Duration::from_secs(60);
|
||||
@@ -222,6 +224,8 @@ impl DataCollector {
|
||||
gpu_pids: None,
|
||||
#[cfg(feature = "gpu")]
|
||||
gpus_total_mem: None,
|
||||
#[cfg(feature = "zfs")]
|
||||
free_arc_mem: false,
|
||||
last_list_collection_time: last_collection_time,
|
||||
should_run_less_routine_tasks: true,
|
||||
}
|
||||
@@ -267,6 +271,11 @@ impl DataCollector {
|
||||
self.get_process_threads = get_process_threads;
|
||||
}
|
||||
|
||||
#[cfg(feature = "zfs")]
|
||||
pub fn set_free_arc_mem(&mut self, free_mem: bool) {
|
||||
self.free_arc_mem = free_mem;
|
||||
}
|
||||
|
||||
/// Refresh sysinfo data. We use sysinfo for the following data:
|
||||
/// - CPU usage
|
||||
/// - Memory usage
|
||||
@@ -463,17 +472,45 @@ impl DataCollector {
|
||||
if self.widgets_to_harvest.use_mem {
|
||||
self.data.memory = memory::get_ram_usage(&self.sys.system);
|
||||
|
||||
#[cfg(feature = "zfs")]
|
||||
{
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
if let Some(arc) = memory::arc::get_arc_usage() {
|
||||
if let Some(mem) = &mut self.data.memory {
|
||||
if self.free_arc_mem {
|
||||
if arc.0.used_bytes > arc.1 {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
mem.used_bytes -= arc.0.used_bytes.saturating_sub(arc.1); // keep arc min like htop
|
||||
}
|
||||
#[cfg(target_os = "freebsd")]
|
||||
{
|
||||
mem.used_bytes += arc.1; // sysinfo subtracts arc_size on freebsd
|
||||
}
|
||||
} else {
|
||||
#[cfg(target_os = "freebsd")]
|
||||
{
|
||||
mem.used_bytes += arc.0.used_bytes;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#[cfg(target_os = "freebsd")]
|
||||
{
|
||||
mem.used_bytes += arc.0.used_bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.data.arc = Some(arc.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
if self.widgets_to_harvest.use_cache {
|
||||
self.data.cache = memory::get_cache_usage(&self.sys.system);
|
||||
}
|
||||
|
||||
self.data.swap = memory::get_swap_usage(&self.sys.system);
|
||||
|
||||
#[cfg(feature = "zfs")]
|
||||
{
|
||||
self.data.arc = memory::arc::get_arc_usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ struct FileSystem {
|
||||
pub fn get_io_usage() -> CollectionResult<IoHarvest> {
|
||||
// TODO: Should this (and other I/O collectors) fail fast? In general, should
|
||||
// collection ever fail fast?
|
||||
#[cfg_attr(not(feature = "zfs"), expect(unused_mut))]
|
||||
let mut io_harvest: HashMap<String, Option<IoData>> =
|
||||
get_disk_info().map(|storage_system_information| {
|
||||
storage_system_information
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#[cfg(all(feature = "zfs", any(target_os = "linux", target_os = "freebsd")))]
|
||||
use super::MemData;
|
||||
|
||||
#[cfg(all(feature = "zfs", any(target_os = "linux", target_os = "freebsd")))]
|
||||
/// Return ARC usage.
|
||||
#[cfg(feature = "zfs")]
|
||||
pub(crate) fn get_arc_usage() -> Option<MemData> {
|
||||
pub(crate) fn get_arc_usage() -> Option<(MemData, u64)> {
|
||||
use std::num::NonZeroU64;
|
||||
|
||||
let (mem_total, mem_used) = {
|
||||
let (mem_total, mem_used, mem_min) = {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_os = "linux")] {
|
||||
// TODO: [OPT] is this efficient?
|
||||
@@ -13,14 +13,16 @@ pub(crate) fn get_arc_usage() -> Option<MemData> {
|
||||
if let Ok(arc_stats) = read_to_string("/proc/spl/kstat/zfs/arcstats") {
|
||||
let mut mem_arc = 0;
|
||||
let mut mem_total = 0;
|
||||
let mut mem_min = 0;
|
||||
let mut zfs_keys_read: u8 = 0;
|
||||
const ZFS_KEYS_NEEDED: u8 = 2;
|
||||
const ZFS_KEYS_NEEDED: u8 = 3;
|
||||
|
||||
for line in arc_stats.lines() {
|
||||
if let Some((label, value)) = line.split_once(' ') {
|
||||
let to_write = match label {
|
||||
"size" => &mut mem_arc,
|
||||
"c_max" => &mut mem_total,
|
||||
"c_min" => &mut mem_min,
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
@@ -39,34 +41,40 @@ pub(crate) fn get_arc_usage() -> Option<MemData> {
|
||||
}
|
||||
}
|
||||
}
|
||||
(mem_total, mem_arc)
|
||||
(mem_total, mem_arc, mem_min)
|
||||
} else {
|
||||
(0, 0)
|
||||
(0, 0, 0)
|
||||
}
|
||||
} else if #[cfg(target_os = "freebsd")] {
|
||||
use sysctl::Sysctl;
|
||||
if let (Ok(mem_arc_value), Ok(mem_sys_value)) = (
|
||||
if let (Ok(mem_arc_value), Ok(mem_sys_value), Ok(mem_min_value)) = (
|
||||
sysctl::Ctl::new("kstat.zfs.misc.arcstats.size"),
|
||||
sysctl::Ctl::new("kstat.zfs.misc.arcstats.c_max"),
|
||||
sysctl::Ctl::new("kstat.zfs.misc.arcstats.c_min"),
|
||||
) {
|
||||
if let (Ok(sysctl::CtlValue::U64(arc)), Ok(sysctl::CtlValue::Ulong(mem))) =
|
||||
(mem_arc_value.value(), mem_sys_value.value())
|
||||
if let (Ok(sysctl::CtlValue::U64(arc)), Ok(sysctl::CtlValue::U64(mem)), Ok(sysctl::CtlValue::U64(min))) =
|
||||
(mem_arc_value.value(), mem_sys_value.value(), mem_min_value.value())
|
||||
{
|
||||
(mem, arc)
|
||||
(mem, arc, min)
|
||||
} else {
|
||||
(0, 0)
|
||||
(0, 0, 0)
|
||||
}
|
||||
} else {
|
||||
(0, 0)
|
||||
(0, 0, 0)
|
||||
}
|
||||
} else {
|
||||
(0, 0)
|
||||
(0, 0, 0)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
NonZeroU64::new(mem_total).map(|total_bytes| MemData {
|
||||
total_bytes,
|
||||
used_bytes: mem_used,
|
||||
NonZeroU64::new(mem_total).map(|total_bytes| {
|
||||
(
|
||||
MemData {
|
||||
total_bytes,
|
||||
used_bytes: mem_used,
|
||||
},
|
||||
mem_min,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -365,6 +365,9 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott
|
||||
# Shows cache and buffer memory
|
||||
#enable_cache_memory = false
|
||||
|
||||
# Subtract freeable ARC from memory usage
|
||||
#free_arc = false
|
||||
|
||||
# How much data is stored at once in terms of time.
|
||||
#retention = "10m"
|
||||
|
||||
@@ -381,6 +384,9 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott
|
||||
# PID, Name, CPU%, Mem%, R/s, W/s, T.Read, T.Write, User, State, Time, GMem%, GPU%
|
||||
#columns = ["PID", "Name", "CPU%", "Mem%", "Virt", "R/s", "W/s", "T.Read", "T.Write", "User", "State", "GMem%", "GPU%"]
|
||||
|
||||
# Gather process child thread information
|
||||
#get_threads = false
|
||||
|
||||
|
||||
# CPU widget configuration
|
||||
#[cpu]
|
||||
|
||||
@@ -228,6 +228,8 @@ fn create_collection_thread(
|
||||
let show_average_cpu = app_config_fields.show_average_cpu;
|
||||
let update_sleep = app_config_fields.update_rate;
|
||||
let get_process_threads = app_config_fields.get_process_threads;
|
||||
#[cfg(feature = "zfs")]
|
||||
let get_arc_free = app_config_fields.free_arc;
|
||||
|
||||
thread::spawn(move || {
|
||||
let mut data_collector = collection::DataCollector::new(filters);
|
||||
@@ -237,6 +239,8 @@ fn create_collection_thread(
|
||||
data_collector.set_unnormalized_cpu(unnormalized_cpu);
|
||||
data_collector.set_show_average_cpu(show_average_cpu);
|
||||
data_collector.set_get_process_threads(get_process_threads);
|
||||
#[cfg(feature = "zfs")]
|
||||
data_collector.set_free_arc_mem(get_arc_free);
|
||||
|
||||
data_collector.update_data();
|
||||
data_collector.data = Data::default();
|
||||
|
||||
@@ -230,6 +230,8 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
|
||||
|
||||
let use_basic_mode = is_flag_enabled!(basic, args.general, config);
|
||||
let expanded = is_flag_enabled!(expanded, args.general, config);
|
||||
#[cfg(feature = "zfs")]
|
||||
let free_arc = is_flag_enabled!(free_arc, args.memory, config);
|
||||
|
||||
// For processes
|
||||
let is_grouped = is_flag_enabled!(group_processes, args.process, config);
|
||||
@@ -329,6 +331,8 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL
|
||||
retention_ms,
|
||||
dedicated_average_row: get_dedicated_avg_row(config),
|
||||
default_tree_collapse: is_default_tree_collapsed,
|
||||
#[cfg(feature = "zfs")]
|
||||
free_arc,
|
||||
};
|
||||
|
||||
let table_config = ProcTableConfig {
|
||||
|
||||
@@ -518,6 +518,15 @@ pub struct MemoryArgs {
|
||||
alias = "enable-cache-memory"
|
||||
)]
|
||||
pub enable_cache_memory: bool,
|
||||
|
||||
#[cfg(feature = "zfs")]
|
||||
#[arg(
|
||||
long,
|
||||
action = ArgAction::SetTrue,
|
||||
help = "Subtract reclaimable ARC from memory.",
|
||||
alias = "free-arc"
|
||||
)]
|
||||
pub free_arc: bool,
|
||||
}
|
||||
|
||||
/// Network arguments/config options.
|
||||
|
||||
@@ -42,6 +42,8 @@ pub(crate) struct GeneralConfig {
|
||||
pub(crate) disable_advanced_kill: Option<bool>, // This does nothing on Windows, but we leave it enabled to make the config file consistent across platforms.
|
||||
// #[cfg(target_os = "linux")]
|
||||
pub(crate) hide_k_threads: Option<bool>,
|
||||
// #[cfg(feature = "zfs")]
|
||||
pub(crate) free_arc: Option<bool>,
|
||||
pub(crate) network_use_bytes: Option<bool>,
|
||||
pub(crate) network_use_log: Option<bool>,
|
||||
pub(crate) network_use_binary_prefix: Option<bool>,
|
||||
|
||||
Reference in New Issue
Block a user