pub const MAX_SMALL: usize = 32_768;
pub const MIN_ALIGN: usize = 8;
pub const MAX_NATIVE_ALIGN: usize = 16;
pub const SPAN_BYTES: usize = 64 * 1024;
pub const CLASSES: [u32; 79] = [
16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128,
144, 160, 176, 192, 208, 224, 240, 256,
288, 320, 352, 384, 416, 448, 480, 512,
576, 640, 704, 768, 832, 896, 960, 1024,
1152, 1280, 1408, 1536, 1664, 1792, 1920, 2048,
2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096,
4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192,
9216, 10240, 11264, 12288, 13312, 14336, 15360, 16384,
18432, 20480, 22528, 24576, 26624, 28672, 30720, 32768,
];
pub const NCLASSES: usize = CLASSES.len();
const GRAIN: usize = 8;
const LOOKUP_LEN: usize = MAX_SMALL / GRAIN + 1;
static LOOKUP: [u8; LOOKUP_LEN] = build_lookup();
const fn build_lookup() -> [u8; LOOKUP_LEN] {
let mut table = [0u8; LOOKUP_LEN];
let mut i = 0;
while i < LOOKUP_LEN {
let size = i * GRAIN;
let mut c = 0;
while c < NCLASSES {
if CLASSES[c] as usize >= size {
break;
}
c += 1;
}
table[i] = c as u8;
i += 1;
}
table
}
#[inline]
#[must_use]
pub fn index_of(size: usize, align: usize) -> Option<usize> {
if size > MAX_SMALL || align > MAX_NATIVE_ALIGN {
return None;
}
let base = LOOKUP[size.div_ceil(GRAIN)] as usize;
if align <= MIN_ALIGN || CLASSES[base].is_multiple_of(align as u32) {
return Some(base);
}
let next = base + 1;
debug_assert!(next < NCLASSES && CLASSES[next].is_multiple_of(align as u32));
Some(next)
}
#[inline]
#[must_use]
pub fn size_of(index: usize) -> usize {
CLASSES[index] as usize
}
const RECIP: [u32; NCLASSES] = {
let mut t = [0u32; NCLASSES];
let mut i = 0;
while i < NCLASSES {
t[i] = ((1u64 << 32).div_ceil(CLASSES[i] as u64)) as u32;
i += 1;
}
t
};
#[inline]
#[must_use]
pub fn slot_of_offset(off: usize, index: usize) -> u32 {
((off as u64 * RECIP[index] as u64) >> 32) as u32
}
#[must_use]
pub const fn slots_per_span(index: usize) -> usize {
SPAN_BYTES / CLASSES[index] as usize
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classes_ascend_and_are_natively_aligned() {
let mut prev = 0u32;
for (i, &c) in CLASSES.iter().enumerate() {
assert!(c > prev, "class {i} = {c} does not exceed {prev}");
assert!(
(c as usize).is_multiple_of(MIN_ALIGN),
"class {c} is not {MIN_ALIGN}-byte aligned"
);
prev = c;
}
}
#[test]
fn the_rounding_bound_is_relative_above_128_and_absolute_below() {
for w in CLASSES.windows(2) {
let (prev, cur) = (w[0], w[1]);
let worst = cur - (prev + 1);
if cur >= 128 {
let rel = f64::from(worst) / f64::from(cur);
assert!(rel < 0.125, "class {prev} -> {cur} wastes {:.1}%", rel * 100.0);
} else {
assert!(worst < GRAIN as u32, "class {prev} -> {cur} wastes {worst} bytes");
}
}
}
#[test]
fn lookup_picks_the_smallest_class_that_fits() {
for size in 1..=MAX_SMALL {
let idx = index_of(size, 1).expect("within the small range");
let picked = size_of(idx);
assert!(picked >= size, "class {picked} too small for {size}");
if idx > 0 {
assert!(
size_of(idx - 1) < size,
"class {} would also have fit {size}",
size_of(idx - 1)
);
}
}
}
#[test]
fn sixteen_byte_alignment_is_served_by_class_choice() {
for size in 1..=MAX_SMALL {
let idx = index_of(size, 16).expect("16 is served natively");
let picked = size_of(idx);
assert!(picked >= size, "class {picked} too small for {size}");
assert!(picked.is_multiple_of(16), "class {picked} cannot align {size} to 16");
}
}
#[test]
fn requests_off_the_class_path_have_no_class() {
assert!(index_of(MAX_SMALL + 1, 1).is_none());
assert!(index_of(usize::MAX, 1).is_none());
assert!(index_of(64, 32).is_none(), "over-alignment belongs to the shim");
}
#[test]
fn every_span_holds_at_least_a_few_slots() {
for i in 0..NCLASSES {
let slots = slots_per_span(i);
assert!(
slots >= 2,
"class {} gets only {slots} slots per span",
size_of(i)
);
}
assert_eq!(SPAN_BYTES % crate::os::PAGE, 0, "a span must be a whole number of pages");
assert!(SPAN_BYTES.is_power_of_two(), "masking needs a power-of-two span");
}
#[test]
fn the_reciprocal_agrees_with_division_everywhere() {
for c in 0..NCLASSES {
let size = size_of(c);
for off in 0..SPAN_BYTES {
assert_eq!(
slot_of_offset(off, c) as usize,
off / size,
"class {c} (size {size}) at offset {off}"
);
}
}
}
}