1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use crate::header::HEADER_SIZE;
/// Number of fixed small-request classes.
pub const NUM_CLASSES: usize = 12;
/// Default block-start alignment used for class sizing.
pub const BLOCK_ALIGNMENT: usize = 64;
/// Fixed small-allocation classes used by Orthotope.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum SizeClass {
/// Requests in `1..=64`.
B64,
/// Requests in `65..=256`.
B256,
/// Requests in `257..=4096`.
B4K,
/// Requests in `4097..=6144`.
B6K,
/// Requests in `6145..=8192`.
B8K,
/// Requests in `8193..=16_384`.
B16K,
/// Requests in `16_385..=32_768`.
B32K,
/// Requests in `32_769..=65_536`.
B64K,
/// Requests in `65_537..=131_072`.
B128K,
/// Requests in `131_073..=262_144`.
B256K,
/// Requests in `262_145..=1_048_576`.
B1M,
/// Requests in `1_048_577..=16_777_216`.
B16M,
}
impl SizeClass {
/// All size classes in ascending order.
pub const ALL: [Self; NUM_CLASSES] = [
Self::B64,
Self::B256,
Self::B4K,
Self::B6K,
Self::B8K,
Self::B16K,
Self::B32K,
Self::B64K,
Self::B128K,
Self::B256K,
Self::B1M,
Self::B16M,
];
#[must_use]
/// Maps a request size to its small-allocation class, or `None` for zero and large requests.
pub const fn from_request(size: usize) -> Option<Self> {
match size {
1..=64 => Some(Self::B64),
65..=256 => Some(Self::B256),
257..=4096 => Some(Self::B4K),
4097..=6144 => Some(Self::B6K),
6145..=8192 => Some(Self::B8K),
8193..=16_384 => Some(Self::B16K),
16_385..=32_768 => Some(Self::B32K),
32_769..=65_536 => Some(Self::B64K),
65_537..=131_072 => Some(Self::B128K),
131_073..=262_144 => Some(Self::B256K),
262_145..=1_048_576 => Some(Self::B1M),
1_048_577..=16_777_216 => Some(Self::B16M),
_ => None,
}
}
#[must_use]
/// Returns the maximum user payload size, in bytes, for this class.
pub const fn payload_size(self) -> usize {
match self {
Self::B64 => 64,
Self::B256 => 256,
Self::B4K => 4_096,
Self::B6K => 6 * 1_024,
Self::B8K => 8_192,
Self::B16K => 16_384,
Self::B32K => 32_768,
Self::B64K => 65_536,
Self::B128K => 131_072,
Self::B256K => 262_144,
Self::B1M => 1_048_576,
Self::B16M => 16_777_216,
}
}
#[must_use]
/// Returns the full allocator block size for this class under the default 64-byte alignment.
///
/// For allocator-specific capacity planning under a custom alignment, prefer
/// [`Self::block_size_for_alignment`] or [`crate::AllocatorConfig::class_block_size`].
pub const fn block_size(self) -> usize {
align_up(self.payload_size() + HEADER_SIZE, BLOCK_ALIGNMENT)
}
#[must_use]
/// Returns the full allocator block size for this class using `alignment`.
///
/// Alignments below the crate's minimum block alignment are clamped up to `64`
/// so this helper remains total even before allocator validation.
pub const fn block_size_for_alignment(self, alignment: usize) -> usize {
align_up(
self.payload_size() + HEADER_SIZE,
effective_block_alignment(alignment),
)
}
#[must_use]
/// Returns the stable dense array index for this class.
pub const fn index(self) -> usize {
match self {
Self::B64 => 0,
Self::B256 => 1,
Self::B4K => 2,
Self::B6K => 3,
Self::B8K => 4,
Self::B16K => 5,
Self::B32K => 6,
Self::B64K => 7,
Self::B128K => 8,
Self::B256K => 9,
Self::B1M => 10,
Self::B16M => 11,
}
}
#[must_use]
/// Returns the largest request still handled by the small-allocation path.
pub const fn max_small_request() -> usize {
Self::B16M.payload_size()
}
}
const fn align_up(value: usize, alignment: usize) -> usize {
let remainder = value % alignment;
if remainder == 0 {
value
} else {
value + (alignment - remainder)
}
}
const fn effective_block_alignment(alignment: usize) -> usize {
if alignment < BLOCK_ALIGNMENT {
BLOCK_ALIGNMENT
} else {
alignment
}
}