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
|
|
@ -71,6 +71,8 @@ pub struct Unconscious {
|
|||
max_concurrent: usize,
|
||||
pub graph_health: Option<crate::subconscious::daemon::GraphHealth>,
|
||||
last_health_check: Option<Instant>,
|
||||
/// Notified when agent state changes (finished, toggled)
|
||||
pub wake: std::sync::Arc<tokio::sync::Notify>,
|
||||
}
|
||||
|
||||
impl Unconscious {
|
||||
|
|
@ -117,6 +119,7 @@ impl Unconscious {
|
|||
agents, max_concurrent,
|
||||
graph_health: None,
|
||||
last_health_check: None,
|
||||
wake: std::sync::Arc::new(tokio::sync::Notify::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,11 +133,13 @@ impl Unconscious {
|
|||
if new_state && !self.agents[idx].is_running() && self.agents[idx].auto.is_some() {
|
||||
let agent_name = self.agents[idx].name.clone();
|
||||
let auto = self.agents[idx].auto.take().unwrap();
|
||||
match prepare_spawn(&agent_name, auto).await {
|
||||
let wake = self.wake.clone();
|
||||
match prepare_spawn(&agent_name, auto, wake).await {
|
||||
Ok(result) => self.complete_spawn(idx, result),
|
||||
Err(auto) => self.abort_spawn(idx, auto),
|
||||
}
|
||||
}
|
||||
self.wake.notify_one(); // wake loop to consider new state
|
||||
Some(new_state)
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +250,7 @@ pub struct SpawnResult {
|
|||
/// Called outside the Unconscious lock.
|
||||
/// On success, auto is consumed (moved into spawned task).
|
||||
/// On failure, auto is returned so it can be restored.
|
||||
pub async fn prepare_spawn(name: &str, mut auto: AutoAgent) -> Result<SpawnResult, AutoAgent> {
|
||||
pub async fn prepare_spawn(name: &str, mut auto: AutoAgent, wake: std::sync::Arc<tokio::sync::Notify>) -> Result<SpawnResult, AutoAgent> {
|
||||
dbglog!("[unconscious] spawning {}", name);
|
||||
|
||||
let def = match defs::get_def(name) {
|
||||
|
|
@ -312,6 +317,7 @@ pub async fn prepare_spawn(name: &str, mut auto: AutoAgent) -> Result<SpawnResul
|
|||
let stats = crate::agent::oneshot::save_agent_log(&auto.name, &agent_clone).await;
|
||||
auto.update_stats(stats);
|
||||
auto.steps = orig_steps;
|
||||
wake.notify_one(); // wake the loop to reap and maybe spawn more
|
||||
(auto, result)
|
||||
});
|
||||
|
||||
|
|
@ -323,8 +329,9 @@ impl Unconscious {
|
|||
pub async fn trigger(&mut self) {
|
||||
self.reap_finished();
|
||||
let to_spawn = self.select_to_spawn();
|
||||
let wake = self.wake.clone();
|
||||
for (idx, name, auto) in to_spawn {
|
||||
match prepare_spawn(&name, auto).await {
|
||||
match prepare_spawn(&name, auto, wake.clone()).await {
|
||||
Ok(result) => self.complete_spawn(idx, result),
|
||||
Err(auto) => self.abort_spawn(idx, auto),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue