Skip to content

Commit a26076f

Browse files
akhil-gautamclaude
andcommitted
perf: throttle system snapshot to 1Hz off System tab, 4Hz on it
snapshot_with_threads rebuilds the full process Vec on every call (hundreds of procs, String allocations, cmd-line clones). Calling it on every 33 ms ratatui tick made every screen feel laggy because the snapshot work fires regardless of which tab the user is on. Also drops the `brew --cache` subprocess from the Homebrew rule — spawning Ruby per scan added ~1s of stall — in favour of a static list of well-known cache paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent beecc1b commit a26076f

4 files changed

Lines changed: 25 additions & 21 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bloat"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
edition = "2021"
55
description = "An htop-style disk storage analyzer and cleanup TUI for macOS"
66

src/app.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,7 @@ fn chrono_now() -> String {
11731173

11741174
pub fn run(mut terminal: DefaultTerminal, mut app: App) -> std::io::Result<()> {
11751175
let mut rx: Option<mpsc::Receiver<ScanProgress>> = None;
1176+
let mut last_snapshot = std::time::Instant::now() - std::time::Duration::from_secs(10);
11761177

11771178
loop {
11781179
// Check quit first — before any auto-start logic
@@ -1188,10 +1189,18 @@ pub fn run(mut terminal: DefaultTerminal, mut app: App) -> std::io::Result<()> {
11881189
rx = Some(app.start_scan());
11891190
}
11901191

1191-
// Always collect a live snapshot so the alert engine stays current.
1192-
// When paused, we don't replace sys_snapshot (which holds the live view
1193-
// used as the base for the UI), but we still run alerts against fresh data.
1194-
{
1192+
// Throttle snapshot collection. snapshot_with_threads rebuilds the
1193+
// full process Vec on every call (heavy: hundreds of procs, String
1194+
// allocations, cmd-line clones), so calling it on every 33 ms tick
1195+
// makes every screen feel laggy. The System tab needs ~4 fps to feel
1196+
// live; other tabs only need the alert engine to stay current.
1197+
let snapshot_interval = if app.tab == Tab::System {
1198+
std::time::Duration::from_millis(250)
1199+
} else {
1200+
std::time::Duration::from_millis(1000)
1201+
};
1202+
if last_snapshot.elapsed() >= snapshot_interval {
1203+
last_snapshot = std::time::Instant::now();
11951204
let expanded_pid = app.system_tab.expanded_pid;
11961205
let snap = app.sys_monitor.snapshot_with_threads(
11971206
std::time::Duration::from_secs(1),

src/rules/homebrew.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// and /Users/<user>/Library/Caches/Homebrew on Intel; we just probe both.
55

66
use std::path::PathBuf;
7-
use std::process::Command;
87

98
use crate::tree::FsTree;
109

@@ -23,21 +22,17 @@ impl CleanupRule for HomebrewCacheRule {
2322
fn safety(&self) -> Safety { Safety::Safe }
2423

2524
fn detect(&self, _tree: &FsTree) -> Vec<CleanupItem> {
25+
// Probe well-known cache paths directly — never spawn `brew --cache`,
26+
// which costs ~1s of Ruby startup per scan.
2627
let mut paths: Vec<PathBuf> = Vec::new();
27-
28-
if let Ok(out) = Command::new("brew").arg("--cache").output() {
29-
if out.status.success() {
30-
let p = String::from_utf8_lossy(&out.stdout).trim().to_string();
31-
if !p.is_empty() {
32-
paths.push(PathBuf::from(p));
33-
}
34-
}
35-
}
36-
if paths.is_empty() {
37-
if let Some(home) = dirs::home_dir() {
38-
let p = home.join("Library/Caches/Homebrew");
39-
if p.exists() {
40-
paths.push(p);
28+
if let Some(home) = dirs::home_dir() {
29+
for candidate in [
30+
home.join("Library/Caches/Homebrew"),
31+
PathBuf::from("/opt/homebrew/Library/Homebrew/cache"),
32+
PathBuf::from("/usr/local/Library/Homebrew/cache"),
33+
] {
34+
if candidate.exists() {
35+
paths.push(candidate);
4136
}
4237
}
4338
}

0 commit comments

Comments
 (0)