From e406ee8347c7890616eaf4ba3138a3dba32dcc0c Mon Sep 17 00:00:00 2001 From: Clement Tsang <34804052+ClementTsang@users.noreply.github.com> Date: Wed, 20 May 2026 02:11:47 -0400 Subject: [PATCH] other: add explicit `short-gpu-names` option (#2072) This PR adds the option to opt in to using the short GPU names setting. Also fix a test and some docs. --- CHANGELOG.md | 4 +-- .../configuration/command-line-options.md | 3 +- .../configuration/config-file/flags.md | 2 +- .../configuration/config-file/memory-graph.md | 13 ++++++++ sample_configs/default_config.toml | 18 ++++++++++- schema/nightly/bottom.json | 9 +++++- src/app.rs | 1 + src/canvas/widgets/mem_graph.rs | 16 +++++++--- src/constants.rs | 18 ++++++++++- src/options.rs | 19 +++++++++++ src/options/args.rs | 9 ++++++ src/options/config/memory_graph.rs | 6 +++- tests/integration/valid_config_tests.rs | 32 +++++++++++++++---- 13 files changed, 131 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 338759d5..849c7f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,8 @@ That said, these are more guidelines rather than hard rules, though the project - [#2046](https://github.com/ClementTsang/bottom/pull/2046): Add a `show_table_scroll_bar` config option to show a scroll bar on table widgets. - [#2048](https://github.com/ClementTsang/bottom/pull/2048): Add support for a temperature graph to show sensor temperature change over time. - [#2053](https://github.com/ClementTsang/bottom/pull/2053): Add a configurable default sort column for the process widget (`processes.default_sort` or `--process-default-sort`). -- [#1754](https://github.com/ClementTsang/bottom/issues/1754): Add search support in the help dialog. +- [#2066](https://github.com/ClementTsang/bottom/pull/2066): Add search support in the help dialog. +- [#1791](https://github.com/ClementTsang/bottom/pull/1791), [#2072](https://github.com/ClementTsang/bottom/pull/2072): Add support for using a short name for the GPU in memory usage. ### Changes @@ -109,7 +110,6 @@ That said, these are more guidelines rather than hard rules, though the project - [#1891](https://github.com/ClementTsang/bottom/pull/1891): Fix typos in codebase. - [#1896](https://github.com/ClementTsang/bottom/pull/1896): Rename Linux icon to avoid collision with generic "bottom" icon. - - [#1913](https://github.com/ClementTsang/bottom/pull/1913): Add `loongarch64-unknown-linux-gnu` binary build target in CI. - [#1914](https://github.com/ClementTsang/bottom/pull/1914): Add `aarch64-linux-android` binary build target in CI (with diff --git a/docs/content/configuration/command-line-options.md b/docs/content/configuration/command-line-options.md index d191df33..19f16369 100644 --- a/docs/content/configuration/command-line-options.md +++ b/docs/content/configuration/command-line-options.md @@ -66,7 +66,8 @@ see information on these options by running `btm -h`, or run `btm --help` to dis | ---------------------------- | --------------------------------------------------------- | | `--memory_legend ` | 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. | +| `--free_arc` | Subtract ARC memory that can be freed from memory usage. | +| `--short_gpu_names` | Use short GPU names in the memory widget. | ## Network Options diff --git a/docs/content/configuration/config-file/flags.md b/docs/content/configuration/config-file/flags.md index f857b18e..7a609b8f 100644 --- a/docs/content/configuration/config-file/flags.md +++ b/docs/content/configuration/config-file/flags.md @@ -59,4 +59,4 @@ each time: | `disable_keys` | Boolean | Disables keyboard shortcuts, including the ones that stop bottom. | | `no_write` | Boolean | Disables writing to the config file. | | `hide_k_threads` | Boolean | Deprecated - use `processes.hide_k_threads`. Hide kernel threads from being shown. | -| `free_arc` | Boolean | Deprecated - use `memory.free_arc`. Subtract freeable ARC from memory usage. | +| `free_arc` | Boolean | Deprecated - use `memory.free_arc`. Subtract ARC memory that can be freed from memory usage. | diff --git a/docs/content/configuration/config-file/memory-graph.md b/docs/content/configuration/config-file/memory-graph.md index ced02c42..9cb19322 100644 --- a/docs/content/configuration/config-file/memory-graph.md +++ b/docs/content/configuration/config-file/memory-graph.md @@ -17,11 +17,24 @@ legend_position = "top-left" On Linux, you can change whether the memory used by [cache/slabs](https://serverfault.com/a/1025189) is collected and shown. By default, it is `false`. + + ```toml [memory_graph] cache_memory = true ``` +## Short GPU names + +If GPU support is enabled, you can use `short_gpu_names` to display simplified GPU names in the memory graph widget +instead of the full GPU names. If enabled, then if there's only one GPU, it'll just list the entry as `GPU`; +if there are multiple GPUs, it'll use entries like `GPU0`, `GPU1`, etc. By default, this is disabled. + +```toml +[memory_graph] +short_gpu_names = true +``` + ## Subtract free-able ARC from memory If ZFS is detected (note that the `zfs` feature must be enabled if built manually), you can enable `memory_graph.free_arc` to diff --git a/sample_configs/default_config.toml b/sample_configs/default_config.toml index c0b1850e..ebba087a 100644 --- a/sample_configs/default_config.toml +++ b/sample_configs/default_config.toml @@ -141,7 +141,7 @@ #enable_cache_memory = false # Deprecated - use memory.free_arc. -# Subtract freeable ARC from memory usage +# Subtract ARC memory that can be freed from memory usage. #free_arc = false # How much data is stored at once in terms of time. @@ -319,6 +319,22 @@ #whole_word = false +# Memory widget configuration +#[memory_graph] + +# Where to place the legend for the memory widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right". +#legend_position = "top-right" + +# Shows cache and buffer memory. Linux only. +#cache_memory = false + +# Subtract ARC memory that can be freed from memory usage. Only available if the ZFS feature is enabled when built. +#free_arc = false + +# Use short GPU names (e.g. "GPU" or "GPU0", "GPU1") instead of full GPU names. Only available if the GPU feature is enabled when built. +#short_gpu_names = false + + # Network widget configuration #[network_graph] # By default, there are no network interface filters enabled. An example use case is provided below. diff --git a/schema/nightly/bottom.json b/schema/nightly/bottom.json index 2a6affb7..c76c9f46 100644 --- a/schema/nightly/bottom.json +++ b/schema/nightly/bottom.json @@ -694,7 +694,7 @@ ] }, "free_arc": { - "description": "Whether to subtract freeable ARC from memory usage.", + "description": "Whether to subtract ARC that can be freed from memory usage.", "type": [ "boolean", "null" @@ -706,6 +706,13 @@ "string", "null" ] + }, + "short_gpu_names": { + "description": "Whether to use short GPU names in the memory widget.", + "type": [ + "boolean", + "null" + ] } } }, diff --git a/src/app.rs b/src/app.rs index 2a140885..e2e934cd 100644 --- a/src/app.rs +++ b/src/app.rs @@ -57,6 +57,7 @@ pub struct AppConfigFields { pub disable_click: bool, pub disable_keys: bool, pub enable_gpu: bool, + pub short_gpu_names: bool, pub enable_cache_memory: bool, pub show_table_scroll_position: bool, pub show_table_scroll_bar: bool, diff --git a/src/canvas/widgets/mem_graph.rs b/src/canvas/widgets/mem_graph.rs index ed46d939..b45621c0 100644 --- a/src/canvas/widgets/mem_graph.rs +++ b/src/canvas/widgets/mem_graph.rs @@ -136,8 +136,10 @@ impl Painter { { let mut colour_index = 0; let gpu_styles = &self.styles.gpu_colours; + let short_gpu_names = app_state.app_config_fields.short_gpu_names; + let gpu_count = data.gpu_harvest.len(); - for (name, harvest) in &data.gpu_harvest { + for (gpu_index, (name, harvest)) in data.gpu_harvest.iter().enumerate() { if let Some(gpu_data) = data.time_series_data.gpu_mem.get(name) { let style = { if gpu_styles.is_empty() { @@ -150,15 +152,19 @@ impl Painter { } }; - let display_name = if data.gpu_harvest.len() == 1 { - &"GPU".to_string() + let display_name = if short_gpu_names { + if gpu_count == 1 { + "GPU".to_string() + } else { + format!("GPU{gpu_index}") + } } else { - name // TODO: REALLY figure out how to line this up better + name.clone() }; graph_data( &mut points, - display_name, + &display_name, Some(harvest), time, gpu_data, diff --git a/src/constants.rs b/src/constants.rs index 0434c7b2..433a2187 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -390,7 +390,7 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott #enable_cache_memory = false # Deprecated - use memory.free_arc. -# Subtract freeable ARC from memory usage +# Subtract ARC memory that can be freed from memory usage. #free_arc = false # How much data is stored at once in terms of time. @@ -568,6 +568,22 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott #whole_word = false +# Memory widget configuration +#[memory_graph] + +# Where to place the legend for the memory widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right". +#legend_position = "top-right" + +# Shows cache and buffer memory. Linux only. +#cache_memory = false + +# Subtract ARC memory that can be freed from memory usage. Only available if the ZFS feature is enabled when built. +#free_arc = false + +# Use short GPU names (e.g. "GPU" or "GPU0", "GPU1") instead of full GPU names. Only available if the GPU feature is enabled when built. +#short_gpu_names = false + + # Network widget configuration #[network_graph] # By default, there are no network interface filters enabled. An example use case is provided below. diff --git a/src/options.rs b/src/options.rs index ae8edd65..2ddd76c2 100644 --- a/src/options.rs +++ b/src/options.rs @@ -440,6 +440,7 @@ pub(crate) fn init_app(args: BottomArgs, config: Config) -> Result<(App, BottomL disable_click: is_flag_enabled!(disable_click, args.general, config), disable_keys: is_flag_enabled!(disable_keys, args.general, config), enable_gpu: get_enable_gpu(args, config), + short_gpu_names: get_short_gpu_names(args, config), enable_cache_memory: get_enable_cache_memory(args, config), show_table_scroll_position: is_flag_enabled!( show_table_scroll_position, @@ -1082,6 +1083,24 @@ fn get_enable_gpu(_: &BottomArgs, _: &Config) -> bool { false } +#[cfg(feature = "gpu")] +fn get_short_gpu_names(args: &BottomArgs, config: &Config) -> bool { + if args.memory.short_gpu_names { + return true; + } + + config + .memory_graph + .as_ref() + .and_then(|m| m.short_gpu_names) + .unwrap_or(false) +} + +#[cfg(not(feature = "gpu"))] +fn get_short_gpu_names(_: &BottomArgs, _: &Config) -> bool { + false +} + #[cfg(not(target_os = "windows"))] fn get_enable_cache_memory(args: &BottomArgs, config: &Config) -> bool { enabled_option_with_deprecated!( diff --git a/src/options/args.rs b/src/options/args.rs index f5d286e7..aa7de9d7 100644 --- a/src/options/args.rs +++ b/src/options/args.rs @@ -540,6 +540,15 @@ pub struct MemoryArgs { alias = "free-arc" )] pub free_arc: bool, + + #[cfg(feature = "gpu")] + #[arg( + long, + action = ArgAction::SetTrue, + help = "Use short GPU names (e.g. 'GPU' or 'GPU0', 'GPU1') in the memory widget instead of full GPU names.", + alias = "short-gpu-names" + )] + pub short_gpu_names: bool, } /// Network arguments/config options. diff --git a/src/options/config/memory_graph.rs b/src/options/config/memory_graph.rs index 8b4cbbbd..2a6c8216 100644 --- a/src/options/config/memory_graph.rs +++ b/src/options/config/memory_graph.rs @@ -16,7 +16,11 @@ pub struct MemoryGraphConfig { #[cfg_attr(target_os = "windows", allow(dead_code))] pub(crate) cache_memory: Option, - /// Whether to subtract freeable ARC from memory usage. + /// Whether to subtract ARC that can be freed from memory usage. #[cfg_attr(not(feature = "zfs"), allow(dead_code))] pub(crate) free_arc: Option, + + /// Whether to use short GPU names in the memory widget. + #[cfg_attr(not(feature = "gpu"), allow(dead_code))] + pub(crate) short_gpu_names: Option, } diff --git a/tests/integration/valid_config_tests.rs b/tests/integration/valid_config_tests.rs index 1a01e073..d417e31c 100644 --- a/tests/integration/valid_config_tests.rs +++ b/tests/integration/valid_config_tests.rs @@ -1,10 +1,9 @@ //! Tests config files that have sometimes caused issues despite being valid. -use std::{io::Read, thread, time::Duration}; +use std::{io::Read, process::Stdio, thread, time::Duration}; #[cfg(feature = "default")] use std::{io::Write, path::Path}; -use assert_cmd::prelude::*; use predicates::prelude::*; use crate::util::{btm_command, spawn_btm_in_pty}; @@ -279,10 +278,31 @@ fn test_deprecated_temperature() { } /// Test that deprecated warnings are not shown for config options that are not actually set, -/// even when a [flags] section is present. +/// even when a `[flags]` section is present. #[test] fn test_no_spurious_deprecated_warnings() { - btm_command(&["-C", "./tests/valid_configs/empty_flags.toml"]) - .assert() - .stderr(predicate::str::contains("deprecated").not()); + let mut child = btm_command(&["-C", "./tests/valid_configs/empty_flags.toml"]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + thread::sleep(Duration::from_secs(1)); + child.kill().unwrap(); + child.wait().unwrap(); + + let stderr_str = { + let mut stderr = child.stderr.take().unwrap(); + let mut buf = String::new(); + + stderr.read_to_string(&mut buf).unwrap(); + buf + }; + + assert!( + predicate::str::contains("deprecated") + .not() + .eval(&stderr_str), + "Expected no deprecated warnings, but got: {stderr_str}" + ); }