cache hex position

This commit is contained in:
MayaTheShy
2025-11-01 23:50:43 -04:00
parent 7319578b8b
commit a978b2ad68

View File

@@ -25,6 +25,8 @@ use tokio::time::Duration;
static REIFY_COUNT: AtomicUsize = AtomicUsize::new(0); static REIFY_COUNT: AtomicUsize = AtomicUsize::new(0);
static REIFY_TOTAL_NS: AtomicU64 = AtomicU64::new(0); static REIFY_TOTAL_NS: AtomicU64 = AtomicU64::new(0);
static APP_REIFY_COUNT: AtomicUsize = AtomicUsize::new(0); static APP_REIFY_COUNT: AtomicUsize = AtomicUsize::new(0);
static VISIBLE_LIMIT: AtomicUsize = AtomicUsize::new(0);
const VISIBLE_STEP: usize = 12;
use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt}; use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt};
@@ -75,6 +77,9 @@ pub struct HexagonLauncher {
#[serde(skip)] #[serde(skip)]
/// position in the vector is mapped to hex coordinates /// position in the vector is mapped to hex coordinates
apps: Vec<App>, apps: Vec<App>,
#[serde(skip)]
/// cached world coordinates for each app hex
positions: Vec<[f32; 3]>,
} }
impl Default for HexagonLauncher { impl Default for HexagonLauncher {
@@ -84,6 +89,7 @@ impl Default for HexagonLauncher {
pos: [0.0; 3].into(), pos: [0.0; 3].into(),
rot: Quat::IDENTITY.into(), rot: Quat::IDENTITY.into(),
apps: Vec::new(), apps: Vec::new(),
positions: Vec::new(),
} }
} }
} }
@@ -109,6 +115,11 @@ impl ClientState for HexagonLauncher {
// Sort by name // Sort by name
self.apps self.apps
.sort_by_key(|app| app.app.name().unwrap_or_default().to_string()); .sort_by_key(|app| app.app.name().unwrap_or_default().to_string());
// precompute coordinates for each app to avoid recomputing per-reify
self.positions = (0..self.apps.len())
.map(|i| Hex::spiral(i + 1).get_coords())
.collect();
} }
} }
impl Reify for HexagonLauncher { impl Reify for HexagonLauncher {
@@ -167,24 +178,59 @@ impl Reify for HexagonLauncher {
)) ))
.build(), .build(),
) )
.children( // limit how many children we build per-frame to avoid reify explosion;
// increase if performance is acceptable, or implement a pager/virtualization.
.children({
// read configured maximum (fall back to all apps)
let env_max = std::env::var("HEX_MAX_VISIBLE")
.ok()
.and_then(|s| s.parse::<usize>().ok());
let configured_max = env_max.unwrap_or(self.apps.len());
// desired target: if open -> min(configured_max, apps.len()) else 0
let desired = if self.open {
std::cmp::min(configured_max, self.apps.len())
} else {
0
};
// nudge the global visible limit toward desired to spread creation cost
let current = VISIBLE_LIMIT.load(Ordering::Relaxed);
if desired == 0 {
// closing -> quickly collapse
if current != 0 {
VISIBLE_LIMIT.store(0, Ordering::Relaxed);
}
} else if current < desired {
let add = (desired - current).min(VISIBLE_STEP);
VISIBLE_LIMIT.fetch_add(add, Ordering::Relaxed);
} else if current > desired {
// clamp down if configured max reduced
VISIBLE_LIMIT.store(desired, Ordering::Relaxed);
}
let take_n = std::cmp::min(VISIBLE_LIMIT.load(Ordering::Relaxed), self.apps.len());
tracing::debug!(total_apps = self.apps.len(), configured_max, visible = take_n, desired, "building visible app children");
self.open self.open
.then(|| { .then(|| {
self.apps.iter().enumerate().map(|(i, app)| { self.apps
Spatial::default() .iter()
.pos(Hex::spiral(i + 1).get_coords()) .enumerate()
.build() .take(take_n)
.child(app.reify_substate(move |state: &mut HexagonLauncher| { .map(|(i, app)| {
// log & count access to per-app substate Spatial::default()
APP_REIFY_COUNT.fetch_add(1, Ordering::Relaxed); .pos(self.positions[i])
tracing::trace!(index = i, "accessing app substate"); .build()
state.apps.get_mut(i) .child(app.reify_substate(move |state: &mut HexagonLauncher| {
})) // log & count access to per-app substate
}) APP_REIFY_COUNT.fetch_add(1, Ordering::Relaxed);
tracing::trace!(index = i, "accessing app substate");
state.apps.get_mut(i)
}))
})
}) })
.into_iter() .into_iter()
.flatten(), .flatten()
) })
; ;
let elapsed = start.elapsed().as_nanos() as u64; let elapsed = start.elapsed().as_nanos() as u64;