use super::pooling::{service_id, ServiceId};
use hashbrown::HashMap;
use spin::Mutex;
use ruda::runtime::{backend::Runtime, client::ComputeClient, throughput::MemoryAccess};
use crate::library::throughput::LaunchConfig;
const MEMORY_WORKER_SHAPES: usize = 5;
static SATURATING_WORKERS: Mutex<Option<HashMap<(ServiceId, MemoryAccess), u32>>> =
Mutex::new(None);
pub(super) struct WorkerSweep;
impl WorkerSweep {
pub(super) fn shapes<R: Runtime>(
client: &ComputeClient<R>,
config: LaunchConfig,
access: MemoryAccess,
) -> alloc::vec::Vec<LaunchConfig> {
if client.properties().hardware.num_cpu_cores.is_none() {
return alloc::vec![config];
}
if let Some(units) = Self::remembered(client, access) {
return alloc::vec![config.with_units(client, units)];
}
Self::counts(config.ruda_dim.num_elems() as usize)
.into_iter()
.map(|units| config.with_units(client, units as u32))
.collect()
}
fn counts(units: usize) -> alloc::vec::Vec<usize> {
core::iter::successors(Some(units.max(1)), |units| (*units > 1).then(|| units / 2))
.take(MEMORY_WORKER_SHAPES)
.collect()
}
fn remembered<R: Runtime>(client: &ComputeClient<R>, access: MemoryAccess) -> Option<u32> {
let workers = SATURATING_WORKERS.lock();
let workers = workers.as_ref()?;
workers.get(&(service_id(client), access)).copied()
}
pub(super) fn remember<R: Runtime>(client: &ComputeClient<R>, access: MemoryAccess, units: u32) {
let mut workers = SATURATING_WORKERS.lock();
workers
.get_or_insert_with(HashMap::new)
.insert((service_id(client), access), units);
}
}