Expand description
Size classes.
§Why eight subdivisions per octave, not four
Two terms of the accounting contract pull against each other: finer classes cut rounding, coarser classes cut span slack (fewer classes means fewer partial spans sitting around). Both are real, so the choice is not taste.
§8.1 of the RFC settles it. Rounding is the only term that scales with the dataset; slack is O(classes × shards) and constant in the data. Spend the constant to shrink the term that scales. Hence eight subdivisions per octave — worst-case rounding ≈ 11.1 %, against the ~20 % that four subdivisions would give.
Below 128 bytes the classes step by 8, and the bound there is absolute rather than relative: at most 7 bytes wasted, but that is 29 % of a 24-byte class. The relative bound cannot be rescued at that end — 8 bytes is the granularity floor, since finer classes would not keep slots 8-byte aligned. Saying “the step is finer so it costs nothing” would have been wrong, and the class table’s own test said so before this comment was written.
§Why spans are one uniform size after all
The first draft sized spans per class, reasoning that a fixed span size makes slack proportional to the class count — which the decision above deliberately increases. Two things overturned it.
Geometry: dealloc finds a pointer’s span by masking, which needs
uniform span geometry. Variable spans would need a lookup structure
on the free path, paid on every deallocation, to save address space.
And the worry was misplaced. Spans hand out slots by bumping a
cursor, so the untouched tail of a span is mapped but never
resident — it costs address space, not memory. That is why the
accounting splits slack into touched (span_free) and untouched
(virgin): only the first is RSS. A large uniform span whose tail is
never reached is close to free in the metric that matters.
Constants§
- CLASSES
- The class table: every size a slot may have, ascending.
- MAX_
NATIVE_ ALIGN - Strongest alignment served by picking a suitable class rather than by
over-allocating. Requests above this go to the
GlobalAllocshim’s over-aligned path. - MAX_
SMALL - The largest allocation served by a size class. Above this, requests
are mapped directly and returned with
unmap. - MIN_
ALIGN - Alignment every class satisfies natively, because every class is a multiple of it and spans are aligned far beyond it.
- NCLASSES
- Number of size classes.
- SPAN_
BYTES - Every span is this many bytes, whatever class it serves. Uniform
geometry is what lets
deallocfind a span by masking; see the module docs for why the variable-size draft lost. 64 KiB gives the largest class eight slots and the smallest four thousand.
Functions§
- index_
of - The class index serving
sizeatalign, orNonewhen the request belongs on the direct-mapping path (too large, or too strictly aligned to serve from a class). - size_of
- Slot size for a class index.
- slot_
of_ offset - Divide a span offset by a class’s slot size via the reciprocal
table.
offmust be belowSPAN_BYTES. - slots_
per_ span - Slots that fit in a span of this class.