unconscious: event-driven loop via tokio::select!

Replace yield_now() polling with proper event-driven wakeups:
- Add wake: Arc<Notify> to Unconscious struct
- Spawned agents call wake.notify_one() on completion
- Loop uses select! on: unc_rx.changed(), wake.notified(), health timer

Eliminates spinning (was 27.9M iterations per interval).

Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
Kent Overstreet 2026-04-13 22:38:01 -04:00
parent 19789b7e74
commit 4d22a28794
2 changed files with 42 additions and 22 deletions

View file

@ -346,32 +346,44 @@ impl Mind {
let mut s = shared_for_unc.lock().unwrap();
s.unc_idle = true;
}
// Get wake notify for event-driven loop
let wake = unc.lock().await.wake.clone();
let mut health_interval = tokio::time::interval(std::time::Duration::from_secs(600));
health_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
loop {
// Phase 0: health check outside lock (slow I/O)
let needs_health = unc.lock().await.needs_health_refresh();
// Do work: reap finished agents, spawn new ones
let (to_spawn, needs_health) = {
let mut guard = unc.lock().await;
guard.reap_finished();
(guard.select_to_spawn(), guard.needs_health_refresh())
};
// Spawn agents outside lock
for (idx, name, auto) in to_spawn {
match crate::mind::unconscious::prepare_spawn(&name, auto, wake.clone()).await {
Ok(result) => unc.lock().await.complete_spawn(idx, result),
Err(auto) => unc.lock().await.abort_spawn(idx, auto),
}
}
// Health check outside lock (slow I/O)
if needs_health {
if let Ok(store_arc) = access_local() {
let health = crate::subconscious::daemon::compute_graph_health(&store_arc);
unc.lock().await.set_health(health);
}
}
// Phase 1: quick work under lock
let to_spawn = {
let mut guard = unc.lock().await;
guard.reap_finished();
guard.select_to_spawn()
};
// Phase 2: slow work outside lock
for (idx, name, auto) in to_spawn {
match crate::mind::unconscious::prepare_spawn(&name, auto).await {
Ok(result) => unc.lock().await.complete_spawn(idx, result),
Err(auto) => unc.lock().await.abort_spawn(idx, auto),
// Wait for: conscious active, agent finished, or health timer
tokio::select! {
_ = unc_rx.changed() => {
if *unc_rx.borrow() { break; }
}
_ = wake.notified() => {}
_ = health_interval.tick() => {}
}
// Check if conscious became active
if *unc_rx.borrow() { break; }
// Brief yield to not starve other tasks
tokio::task::yield_now().await;
}
}
});
@ -637,7 +649,8 @@ impl Mind {
};
let mut cmds = Vec::new();
let mut dmn_expired = false;
#[allow(unused_assignments)]
let mut _dmn_expired = false;
tokio::select! {
biased;
@ -676,7 +689,7 @@ impl Mind {
}
}
_ = tokio::time::sleep(timeout), if !has_input => dmn_expired = true,
_ = tokio::time::sleep(timeout), if !has_input => _dmn_expired = true,
}
if !self.config.no_agents {