pub enum AffinityIntent {
Inherit,
RandomSubset {
from: BTreeSet<usize>,
count: usize,
},
LlcAligned,
CrossCgroup,
SingleCpu,
Exact(BTreeSet<usize>),
SmtSiblingPair,
}Expand description
Scenario-level affinity intent for a group of workers.
Resolved to a concrete ResolvedAffinity at runtime based on the
cgroup’s effective cpuset and the VM’s topology. When attached to
a WorkSpec, determines per-worker sched_setaffinity masks.
Resolution uses resolve_affinity_for_cgroup().
§Naming pattern (Intent vs Resolved)
AffinityIntent and ResolvedAffinity form a pre/post-resolution
pair. Variant names line up where the same shape exists on both
sides; payload differences encode the intent → concrete-CPU-set
distinction:
AffinityIntent | ResolvedAffinity |
|---|---|
Inherit (no payload) | None |
Exact(BTreeSet<usize>) | Fixed(BTreeSet<usize>) |
RandomSubset { from, count } | Random { from, count } |
SingleCpu (no payload) | SingleCpu(usize) |
LlcAligned / CrossCgroup | Fixed(...) (resolver expands) |
SmtSiblingPair (no payload) | Fixed({sibling_a, sibling_b}) |
Constructor helpers: AffinityIntent::exact takes any
IntoIterator<Item = usize> for the Exact set;
AffinityIntent::random_subset takes the same iterator shape
for the RandomSubset pool plus a sample-count argument.
The SingleCpu pair specifically: AffinityIntent::SingleCpu
expresses “pin to one CPU; resolver picks which based on cgroup
state and worker index”, and ResolvedAffinity::SingleCpu
records the concrete CPU id chosen. Reusing the variant name keeps
the pre/post mapping lexically obvious — payload presence
distinguishes intent from resolution without renaming the variant.
AffinityIntent::RandomSubset carries the resolved pool
(from) and sample size (count) — sampling itself is deferred
to spawn time so each worker gets an independent draw. The
scenario engine’s resolve_affinity_for_cgroup materialises the
pool from cgroup cpuset / topology before constructing this
variant; spawn-time resolve_affinity samples per-worker.
Construct directly via AffinityIntent::random_subset.
Variants§
Inherit
No affinity constraint – inherit from parent cgroup.
RandomSubset
Pin each worker to a random subset of from, sampling count
CPUs per worker. Sampling is deferred to spawn time so each
worker gets an independent draw — mirrors
ResolvedAffinity::Random semantics. Construct with the
resolved pool already materialised; the scenario engine pre-
resolves topology-aware “pick from cgroup state” intent
before building this variant.
LlcAligned
Pin to the CPUs in the worker’s LLC.
CrossCgroup
Pin to all CPUs (crosses cgroup boundaries).
SingleCpu
Pin to a single CPU.
Exact(BTreeSet<usize>)
Pin to an exact set of CPUs.
SmtSiblingPair
Pin all workers in the group to the two SMT siblings of one physical core. Tests how the scheduler handles two compute-bound tasks placed on SMT siblings — both threads contend for the core’s shared front-end / execution resources, exposing scheduler decisions about co-running vs. spreading compute load across cores.
Designed for WorkType::SmtSiblingSpin and other
worker_group_size = 2 variants
(WorkType::FutexPingPong, WorkType::AsymmetricWaker,
WorkType::SignalStorm, etc.) where both workers in a
group are intended to run on a sibling pair. The variant
has no payload — the resolver picks an SMT-sibling pair
from the cgroup’s effective cpuset (or the full topology
when no cpuset is active).
Resolution is performed by the scenario engine’s
resolve_affinity_for_cgroup (topology-aware, not
available at the bare WorkloadHandle::spawn gate). The
resolver searches the cpuset for a physical core with at
least two thread siblings present and resolves to
ResolvedAffinity::Fixed containing those two CPU IDs.
All workers in the group get pinned to that 2-CPU set;
when num_workers == 2 the kernel runs one worker on each
sibling, which is the contention pattern this intent
targets.
Returns an error from the resolver — NOT a silent
fallback — when no SMT-sibling pair is available
(threads_per_core == 1, or the cpuset isolates each
sibling onto a different CPU set). Callers must handle
the error; running WorkType::SmtSiblingSpin without
SMT siblings would produce a misleading result.
Implementations§
Source§impl AffinityIntent
impl AffinityIntent
Sourcepub fn exact(cpus: impl IntoIterator<Item = usize>) -> Self
pub fn exact(cpus: impl IntoIterator<Item = usize>) -> Self
Construct an Exact affinity from any iterator of CPU indices.
Accepts arrays, ranges, Vec, BTreeSet, or any IntoIterator<Item = usize>.
Sourcepub fn random_subset(
from: impl IntoIterator<Item = usize>,
count: usize,
) -> Self
pub fn random_subset( from: impl IntoIterator<Item = usize>, count: usize, ) -> Self
Construct a RandomSubset from a pool iterator and a sample
size. Mirrors the Self::exact constructor’s iterator
flexibility — accepts arrays, Vec, BTreeSet, ranges, or
any IntoIterator<Item = usize> for the pool.
Sampling is deferred to spawn time; each worker gets an
independent count-sized draw from from. count > from.len()
is clamped to from.len() at sample time (topology fact, not
caller error). count == 0 and empty from are rejected at
the spawn-time affinity gate with an actionable diagnostic —
use AffinityIntent::Inherit for no affinity constraint.
Trait Implementations§
Source§impl Clone for AffinityIntent
impl Clone for AffinityIntent
Source§fn clone(&self) -> AffinityIntent
fn clone(&self) -> AffinityIntent
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for AffinityIntent
impl Debug for AffinityIntent
Source§impl Default for AffinityIntent
impl Default for AffinityIntent
Source§fn default() -> AffinityIntent
fn default() -> AffinityIntent
Source§impl<'de> Deserialize<'de> for AffinityIntent
impl<'de> Deserialize<'de> for AffinityIntent
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl Hash for AffinityIntent
impl Hash for AffinityIntent
Source§impl PartialEq for AffinityIntent
impl PartialEq for AffinityIntent
Source§impl Serialize for AffinityIntent
impl Serialize for AffinityIntent
impl Eq for AffinityIntent
impl StructuralPartialEq for AffinityIntent
Auto Trait Implementations§
impl Freeze for AffinityIntent
impl RefUnwindSafe for AffinityIntent
impl Send for AffinityIntent
impl Sync for AffinityIntent
impl Unpin for AffinityIntent
impl UnwindSafe for AffinityIntent
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more