`alloc-checked`: allocation safe collections that don't panic
I work on QuestDB, a database written primarily in Java. We're increasing our use of Rust and, for the first time, Rust will be on the hot path of the query engine.
Heavy queries shouldn't topple a database, even when it's running out of memory.
To do this, we're switching to nightly releases to make use of the Allocator API. The idea is not to use a custom allocator for everything, since that's pretty costly (on dev time), but control the size of data structures that can grow with the query set size such as vectors, queues and hashmaps via specific allocators.
We're then writing custom allocators that wrap the Global allocator, track memory usage and fail allocations early just before running out of memory.
In nightly, the standard library collections such as Vec<T, A: Allocator> allow specifying an allocator. It's a good starting point, but we wanted types that could be swapped into the existing code to eliminate misuse.
In other words, safe APIs that guarantee to never panic! on allocation failure.
Without a wrapper, it's too easy to accidentally call a panic-prone method and have it go unnoticed in a code review.
I couldn't quite find a crate that provided this out of the box, so I wrote one. The alloc-checked crate is still draft-quality code, but I'll be adding more collections over time.
TL;DR: The commonly used APIs often return a Result with AllocError or TryReserveError instead of ().
use alloc_checked::vec::Vec;
let vec = Vec::new_in(your_allocator);
vec.push(42)?; // -> Result<(), TryReserveError>
I hope this is useful to others with similar requirements.