forked from kent/consciousness
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:
parent
19789b7e74
commit
4d22a28794
2 changed files with 42 additions and 22 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue