Expand description
§bitarena
A bitset-accelerated generational arena optimized for sparse iteration.
§Architecture
This crate implements a generational arena using Struct-of-Arrays (SoA) layout with a bitset occupancy tracker. This is the same pattern used internally by ECS frameworks like Bevy, but packaged as a standalone, dependency-free data structure.
§Why this exists
thunderdome and generational-arena use Array-of-Structs (AoS):
Vec<Entry<T>> where Entry<T> = Occupied(gen, T) | Empty(gen, next)This means:
- Every slot pays the cost of an enum discriminant (tag byte + padding)
- Iterating loads every entry (including empty ones) into cache
- For large
T, empty slots waste enormous cache bandwidth - Branch prediction suffers on sparse arenas (random occupied/empty pattern)
§Design (Struct-of-Arrays + Bitset)
occupancy: Vec<u64> — 1 bit per slot, 64 slots per word
generations: Vec<u32> — one generation counter per slot
values: Vec<MaybeUninit<T>> — raw storage, only valid when bit is set
free_list: Vec<u32> — stack of free slot indicesBenefits:
- Iteration scans a tiny bitset (10k slots = 157 bytes) instead of
loading 10k ×
size_of::<Entry<T>>()bytes - Uses hardware
tzcnt/blsrinstructions for branchless bit scanning - Cache lines during iteration contain only occupancy data (no value pollution)
- Values array has zero overhead per empty slot (just uninitialized memory)
- Trivially parallelizable (each
u64word is independent — rayon)
§Quick start
use bitarena::{Arena, Index};
let mut arena = Arena::new();
let idx: Index = arena.insert("hello");
assert_eq!(arena.get(idx), Some(&"hello"));
assert_eq!(arena.remove(idx), Some("hello"));
assert_eq!(arena.get(idx), None);§Feature flags
| Feature | Default | Description |
|---|---|---|
std | yes | Enables std::error::Error impls |
rayon | no | Parallel iteration via rayon |
serde | no | Serialize/deserialize support |
For no_std, disable default features:
[dependencies]
bitarena = { version = "0.1", default-features = false }