From 10541453c4a5a3492d4d127332f3453eac2b1f44 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Sun, 18 Jan 2026 21:38:46 -0600 Subject: [PATCH 1/2] perf: reduce unnecessary daemon cloning in loops Optimize check_retry and check_cron_schedules to avoid cloning entire daemon collections upfront. Instead, collect only daemon IDs first, then look up individual daemons when needed. This reduces memory allocations when most daemons don't need processing: - check_retry: only clones daemons that actually need retrying - check_cron_schedules: only clones daemons with cron schedules Co-Authored-By: Claude Opus 4.5 --- Cargo.lock | 1 + src/supervisor.rs | 60 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 851822ca..556f5bfe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1882,6 +1882,7 @@ dependencies = [ "indexmap", "interprocess", "itertools 0.14.0", + "libc", "log", "miette", "mime_guess", diff --git a/src/supervisor.rs b/src/supervisor.rs index 8e494ccd..130d1323 100644 --- a/src/supervisor.rs +++ b/src/supervisor.rs @@ -133,19 +133,32 @@ impl Supervisor { } async fn check_retry(&self) -> Result<()> { - let state_file = self.state_file.lock().await; - let daemons_to_retry: Vec<(String, Daemon)> = state_file - .daemons - .iter() - .filter(|(_id, d)| { - // Daemon is errored, not currently running, and has retries remaining - d.status.is_errored() && d.pid.is_none() && d.retry > 0 && d.retry_count < d.retry - }) - .map(|(id, d)| (id.clone(), d.clone())) - .collect(); - drop(state_file); + // Collect only IDs of daemons that need retrying (avoids cloning entire Daemon structs) + let ids_to_retry: Vec = { + let state_file = self.state_file.lock().await; + state_file + .daemons + .iter() + .filter(|(_id, d)| { + // Daemon is errored, not currently running, and has retries remaining + d.status.is_errored() + && d.pid.is_none() + && d.retry > 0 + && d.retry_count < d.retry + }) + .map(|(id, _d)| id.clone()) + .collect() + }; - for (id, daemon) in daemons_to_retry { + for id in ids_to_retry { + // Look up daemon when needed (it may have changed since we collected IDs) + let daemon = { + let state_file = self.state_file.lock().await; + match state_file.daemons.get(&id) { + Some(d) => d.clone(), + None => continue, // Daemon was removed + } + }; info!( "retrying daemon {} ({}/{} attempts)", id, @@ -1029,9 +1042,28 @@ impl Supervisor { use std::str::FromStr; let now = chrono::Local::now(); - let daemons = self.state_file.lock().await.daemons.clone(); - for (id, daemon) in daemons { + // Collect only IDs of daemons with cron schedules (avoids cloning entire HashMap) + let cron_daemon_ids: Vec = { + let state_file = self.state_file.lock().await; + state_file + .daemons + .iter() + .filter(|(_id, d)| d.cron_schedule.is_some() && d.cron_retrigger.is_some()) + .map(|(id, _d)| id.clone()) + .collect() + }; + + for id in cron_daemon_ids { + // Look up daemon when needed + let daemon = { + let state_file = self.state_file.lock().await; + match state_file.daemons.get(&id) { + Some(d) => d.clone(), + None => continue, + } + }; + if let Some(schedule_str) = &daemon.cron_schedule && let Some(retrigger) = daemon.cron_retrigger { From a9c2fa9c669901e1202449e603be73d3ba8eeb43 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Sun, 18 Jan 2026 21:45:20 -0600 Subject: [PATCH 2/2] fix: re-verify retry criteria after daemon lookup Address review feedback: re-check that daemon still meets retry criteria after fetching it, since state may have changed between ID collection and processing. Co-Authored-By: Claude Opus 4.5 --- src/supervisor.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/supervisor.rs b/src/supervisor.rs index 130d1323..66a4cc5d 100644 --- a/src/supervisor.rs +++ b/src/supervisor.rs @@ -151,12 +151,20 @@ impl Supervisor { }; for id in ids_to_retry { - // Look up daemon when needed (it may have changed since we collected IDs) + // Look up daemon when needed and re-verify retry criteria + // (state may have changed since we collected IDs) let daemon = { let state_file = self.state_file.lock().await; match state_file.daemons.get(&id) { - Some(d) => d.clone(), - None => continue, // Daemon was removed + Some(d) + if d.status.is_errored() + && d.pid.is_none() + && d.retry > 0 + && d.retry_count < d.retry => + { + d.clone() + } + _ => continue, // Daemon was removed or no longer needs retry } }; info!(