#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum Region {
Sort,
Prefilter,
Assemble,
Reduce,
}
impl Region {
const fn work_per_worker(self) -> usize {
match self {
Region::Sort => 10_000,
Region::Prefilter => 64,
Region::Assemble => 128,
Region::Reduce => 16,
}
}
}
pub(crate) fn workers(region: Region, work: usize, threads: usize) -> usize {
if threads <= 1 {
return 1;
}
(work / region.work_per_worker()).clamp(1, threads)
}
#[cfg(test)]
const DECISIONS: &[(Region, usize, usize, usize)] = &[
(Region::Sort, 0, 8, 1),
(Region::Sort, 19_999, 8, 1),
(Region::Sort, 20_000, 8, 2),
(Region::Sort, 20_000, 2, 2),
(Region::Sort, 100_000, 2, 2),
(Region::Sort, 100_000, 4, 4),
(Region::Sort, 100_000, 8, 8),
(Region::Sort, 235_503, 8, 8),
(Region::Prefilter, 98, 8, 1),
(Region::Prefilter, 127, 8, 1),
(Region::Prefilter, 128, 8, 2),
(Region::Prefilter, 256, 8, 4),
(Region::Prefilter, 512, 8, 8),
(Region::Prefilter, 1_024, 2, 2),
(Region::Prefilter, 1_793, 8, 8),
(Region::Prefilter, 146_240, 8, 8),
(Region::Assemble, 255, 8, 1),
(Region::Assemble, 256, 8, 2),
(Region::Assemble, 1_942, 8, 8),
(Region::Assemble, 1_942, 4, 4),
(Region::Reduce, 4, 8, 1),
(Region::Reduce, 31, 8, 1),
(Region::Reduce, 32, 8, 2),
(Region::Reduce, 48, 2, 2),
(Region::Reduce, 48, 8, 3),
(Region::Reduce, 110, 8, 6),
(Region::Reduce, 614, 8, 8),
(Region::Sort, 1_000_000, 1, 1),
(Region::Reduce, 1_000_000, 1, 1),
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decision_table_is_pinned() {
for &(region, work, threads, want) in DECISIONS {
let got = workers(region, work, threads);
assert_eq!(
got, want,
"{region:?}: work={work} threads={threads} gives {got} workers, pinned at {want}"
);
}
}
#[test]
fn workers_never_exceed_the_budget() {
for region in [
Region::Sort,
Region::Prefilter,
Region::Assemble,
Region::Reduce,
] {
for threads in 1..=16 {
for work in [0, 1, 63, 1_000, 1_000_000, usize::MAX] {
let got = workers(region, work, threads);
assert!(got >= 1 && got <= threads, "{region:?} {work} {threads}");
}
}
}
}
}