Skip to content

Display system swap usage in the TUI memory section (view mode) #220

Description

@bdutta

Summary

all-smi already collects and exports system swap statistics on every platform, but the TUI view mode never displays them. This issue tracks surfacing swap usage (total / used / free) in the interactive view so users can spot swap pressure at a glance — most importantly on Apple Silicon, where an over-sized model or mismatched inference-engine parameters spill unified memory into swap and silently degrade throughput.

The data plumbing is already in place; this is primarily a rendering enhancement.

Background

The requester monitors AI inference workloads on Apple Silicon. When a model or its runtime parameters don't fit the available unified memory, macOS begins swapping, which tanks inference performance without an obvious signal. They want a single pane of glass in all-smi view that shows when the system is swapping.

Current state of swap support across the codebase:

Layer Status Reference
Data model (MemoryInfo has swap_{total,used,free}_bytes) src/device/types.rs:365-378
macOS collection (sysinfo total/used/free_swap()) src/device/memory_macos.rs:67-69
Linux collection (/proc/meminfo SwapTotal/SwapFree) src/device/memory_linux.rs:105-106,137-139
Windows collection (page file via sysinfo) src/device/memory_windows.rs:70-72
Prometheus/API export (all_smi_swap_{total,used,free}_bytes) src/api/metrics/memory.rs:75-113,167
Public lib API + docs docs/LIB_mode.md:494-518
TUI detailed memory section not displayed src/ui/renderers/memory_renderer.rs:58-165
TUI compact local header ❌ RAM only, no swap src/ui/local_header.rs:197-219

Note: README.md:438-439,878 already advertises "Swap space monitoring" / "System and swap memory statistics," so this is also a docs-vs-UI consistency fix — the feature is claimed but invisible in the primary interface.

Proposed Solution

Render swap in the detailed memory section (print_memory_info), which appears in both local mode (src/view/frame_renderer.rs:756) and cluster/remote mode (src/view/frame_renderer.rs:603).

Recommended approach — a dedicated swap bar under the existing memory bar:

  1. Add a BarSegment::swap_used(value) helper with a distinct color (e.g. magenta/orange) in src/ui/widgets.rs, alongside memory_used/memory_buffers/memory_cache (lines 283-293).
  2. In print_memory_info (src/ui/renderers/memory_renderer.rs), after the existing Mem bar, draw a second Swap bar via draw_bar_multi using swap_total_bytes as the total and a swap_used segment, with a X.XGB label. Add Swap: <used>/<total>GB to the info line or bar label.
  3. Only render the swap row when swap_total_bytes > 0 (mirrors the API exporter guard at src/api/metrics/memory.rs:76) so hosts without swap stay uncluttered. Always render it when swap_used_bytes > 0.
  4. Emphasize active swapping: color the swap value/bar amber or red when swap_used_bytes > 0 (or above a small threshold). This is the core signal the requester needs.

Optional secondary: append a compact Swp <used>GB indicator (red when > 0) to the local header (draw_ram_sparkline, src/ui/local_header.rs:197) so the top summary line also flags swapping.

Alternatives considered:

  • Inline text only (add Swap: to the existing Total/Used/Avail/Util line, no bar): least code, but that line is already near the width budget and a bar is more legible.
  • Swap as a segment inside the RAM bar: rejected — swap is backing store, not physical RAM; merging them misrepresents capacity.

Implementation Notes

  • macOS dynamic swap: macOS manages swap dynamically (dynamic_pager); swap_total_bytes may legitimately be 0 until the OS creates a swap file, then grow. The "show only when swap_total > 0" rule makes the swap row appear exactly when swap exists — desirable. Verify sysinfo's total_swap() reflects sysctl vm.swapusage on target macOS versions.
  • macOS compression caveat: macOS compresses memory before swapping; "swap used" is post-compression bytes written to disk, distinct from compressed-but-resident memory. Keep the label simply "Swap" to avoid implying it fully captures memory pressure.
  • Layout / height budget: adding a swap row adds one line to the memory section. In cluster mode, many nodes stack vertically — confirm per-node height accounting and the function-key reservation still hold (see CLAUDE.md "Content Overflow"; src/view/frame_renderer.rs). Conditional rendering keeps non-swap hosts unaffected.
  • Mock server: Apple Silicon and NVIDIA mock templates hardcode swap to 0 (src/mock/templates/apple_silicon.rs:416-418,479-481; src/mock/templates/nvidia.rs:622-624,685-687), so the feature can't currently be demoed via mock. Set realistic non-zero swap (the generic generator already models swap growth in src/mock/metrics/memory.rs) for at least one template so reviewers can exercise the new UI.
  • Tests: memory_renderer.rs unit tests already build MemoryInfo with non-zero swap (lines 183-185); extend them to assert the swap row renders when present and is omitted when swap_total_bytes == 0.
  • Docs/help: update the memory legend in the help overlay (src/ui/help.rs:272,293) and the README memory section to describe the swap row and its colors.

Affected files (primary): src/ui/renderers/memory_renderer.rs, src/ui/widgets.rs, src/ui/local_header.rs (optional), src/mock/templates/apple_silicon.rs (+ nvidia.rs), src/ui/help.rs, README.md.

Acceptance Criteria

  • View mode displays swap (used / total, plus a bar) in the memory section for both local and cluster/remote modes when swap_total_bytes > 0.
  • The swap row is hidden on hosts with no swap (swap_total_bytes == 0) to avoid clutter.
  • Active swapping is visually emphasized (e.g. amber/red) when swap_used_bytes > 0.
  • Verified on Apple Silicon (macOS) with real swap, and on Linux via /proc/meminfo.
  • Mock server produces non-zero swap for at least one template so the UI is demoable (all-smi-mock-server + all-smi view).
  • No layout regression: header, function keys, and per-node spacing remain correct in cluster mode with many nodes.
  • Renderer unit tests cover both swap-present and swap-absent cases.
  • Help legend and README updated to document the swap display.

Original Suggestion

Title: Would be nice to show swap usage (going beyond simple "Disk /" usage)

Especially when working with AI workloads, s.a. on Apple-Silicon, a poor fit, poorly matched inference engine parameters, can lead to swap usage, degrading performance. It'd be good to have a single pane of glass view, in all-smi to see the swap usage on such a system.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions