Skip to main content

PER_CLASS_CAP

Constant PER_CLASS_CAP 

Source
pub const PER_CLASS_CAP: u32 = 16_777_216;
Expand description

Spans one class may hold at once, per heap — a runaway guard, not a policy. At 64 KiB a span, this bounds one class at roughly 4 GiB per shard, which no correct program reaches by accident.

torajs-mmalloc shipped without any cap and paid for it (c2970b6d): a legal program exhausted a class, the allocator returned None, and the null propagated into a write — a SIGSEGV on correct code. What actually protects a Rust program is that a null from alloc becomes handle_alloc_error and a clean abort; the cap only makes runaway growth arrive there sooner.

The inherited value was 64 spans — 4 MiB a class — and it was wrong by three orders of magnitude for this engine. The standard library found it on the first run that put real work through the allocator: a test holding tens of thousands of buffers of one size hit the ceiling and aborted with “memory allocation of 6152 bytes failed” while the machine had gigabytes free. A number that is right for a JavaScript runtime’s object churn is not right for a data engine, and copying it across was the mistake.

Heap::with_class_cap takes a tighter bound where one is wanted — which is how the exhaustion path stays testable now that the default is out of reach.

The same lesson, second verse: the raise above was silently pinned by its own u16 — 65,535 spans × 64 KiB is a hidden 4 GiB ceiling per class, and the first hour-long soak found it: a 3-byte-value storm filled the 16 B class and the process aborted with “memory allocation of 3 bytes failed” on a box with 48 GiB free. The counter is now u32 and the guard sits at 1 TiB per class — memory governance belongs to maxmemory and the tier budget, never to an invisible allocator constant.