ADR-0001: Memory-Mapped Storage Strategy
Date: 2026-01-18
Status: Accepted
Context
Chassis is designed to operate across a wide range of environments, from resource-constrained edge devices (e.g., Raspberry Pi) to high-memory servers. A core requirement is the ability to store and search vector datasets that may exceed available physical RAM.
Traditional approaches present fundamental limitations:
- Standard file I/O (
read/write) incurs kernel-to-user copying overhead and deserialization costs, resulting in microsecond-scale access latency. - Loading the full dataset into heap-allocated structures (
Vec<f32>) causes long startup times and introduces hard memory ceilings, often leading to OOM failures. - Copy-based access patterns prevent the system from fully exploiting CPU cache locality during distance computation.
The system therefore requires a persistence mechanism that:
- supports datasets larger than RAM,
- provides pointer-dereference-level access latency (~ns),
- minimizes startup time,
- and integrates cleanly with zero-copy search and linking logic.
Decision
Chassis will use memory-mapped I/O (mmap) as the exclusive mechanism for data access and persistence.
The design has the following properties:
-
Single File Backing The entire index—vectors, graph topology, and metadata—is stored in a single contiguous file on disk.
-
OS-Managed Caching Page caching, eviction (LRU), and write-back behavior are delegated entirely to the operating system’s virtual memory manager (VMM).
-
Zero-Copy Read Path All reads are performed by casting raw pointers (
*const u8) into typed views (&[f32],&NodeRecord) directly within the mapped address space. No intermediate buffers or heap allocations are permitted on the read path. (Amended 2026-10-03: search allocates a visited set and heaps per query, andread_node_recordreturns an owned record. Vector and neighbor reads themselves do not allocate.) -
Cross-Platform Abstraction The implementation relies on the
memmap2crate, providing a safe and portable abstraction overmmap(POSIX) andCreateFileMapping(Windows).
Consequences
Positive
-
Zero-Copy Access Retrieving a vector becomes pure pointer arithmetic. On a cache hit, access latency is on the order of a few nanoseconds, enabling high arithmetic density during distance computation.
-
Instant Startup Opening a large index (e.g., 100GB) completes in milliseconds, as only the virtual address space is mapped; no data is eagerly loaded into RAM.
-
Burst-Friendly Durability Writes occur at memory speed, with dirty pages flushed asynchronously by the OS. Explicit durability boundaries are provided via
commit()(fsync), allowing callers to trade latency for persistence guarantees.
Negative
-
Use of
unsafeRust Memory-mapped access requiresunsafeblocks. Chassis assumes responsibility for validating alignment, bounds, and structural integrity before casting pointers to typed references. -
Non-Standard I/O Failure Modes Hardware-level I/O failures (e.g., disk full, corrupted blocks) may manifest as
SIGBUSrather than recoverableResult::Errvalues. While rare in typical deployments, this requires operational awareness. -
Complex File Growth Semantics The backing file cannot be grown transparently. Expanding capacity requires explicit truncation and re-mapping (
ensure_capacity), which invalidates all previously derived pointers. As a result, references into the mmap must never be held across insertion or growth boundaries.
Compliance
This decision is enforced throughout the codebase:
Storage::get_vector_slicereturns&[f32]backed directly by the memory map, strictly enforcing zero-copy access.Storage::ensure_capacitymanages file growth and re-mapping, ensuring page-aligned (4KB) expansion.- All file access in
chassis-coreis routed exclusively through theStorageabstraction; direct use ofstd::fs::Filefor reads or writes is prohibited.