(docs) update changelog
(bump) v0.2.1
(fb) do bounds check before pointer arithmetic
This crate allows you to create a simple bump-allocated arena. It takes advantage of running on modern operating systems to implement its backing storage as a virtual memory allocation. As such, on supported platforms, the arena will not use physical pages until you issue the first write to them.
The allocator's API has been kept fairly simplistic and minimal. This is not
meant to be a general-purpose allocator. It is meant for creating scratch space
to bundle together allocations/deallocations for objects with similar
lifetimes. This crate is designed to be easily ported to other platforms,
including ones that do not expose the full Rust std
library.
There are tests, but this crate uses a lot of unsafe
code and the soundness
is far from proven. Most likely it will fall over if you are doing extremely
large allocations, "weird" (negative/zero-sized) allocations, or allocations
that exhaust or nearly exhaust the backing storage.
Reset currently does not zero memory between calls, theoretically this could be provided for "no cost" on platforms with real virtual memory by releasing and re-creating the reservation, however that would be quite expensive to provide in the physically-backed fallback allocator. This may change in the future if it causes me great pain. However please note that the current recycling behavior is guaranteed by our tests and API docs. If it is changed in the future it will constitute a breaking change.
Move the examples from this README
into Doc-tests and expand on them.
Look into supporting allocator-api2
for people using stable
Rust to give them a safe API.
This is alpha quality software. Any use is done at your own risk.
I urge you not to use this crate in security-sensitive contexts. By its nature it recycles memory, and all its memory is mapped R/W. It is fairly easy to do terrible things to your neighbors, or otherwise leak their secrets.
Also this is also most emphatically not meant to be a general purpose global
allocator. The support for the allocator_api
is mostly convenience for doing
placement new
inside of std::collections
.
This crate is primarily meant for doing rapid allocation/deallocation of groups of objects with a fixed lifetime. For e.g. an arena for allocating objects that live for one frame of a video game, or allocating objects that live during a request-response cycle.
Include this in your Cargo.toml
as follows:
# with nightly-only (!) allocator_api
# make sure to add `#![feature(allocator_api)] to your crate
vm-arena = { version = "0.1", features = ["allocator-api"] }
# with multi-threading
vm-arena = { version = "0.1", features = ["smp"] }
# force the fallback allocator even on supported platform(s)
vm-arena = { version = "0.1", features = ["fallback"] }
# without multi-threading
vm-arena = "0.1"
You may get a build-time error saying src/os.rs
or src/os/mod.rs
was not
found. What that means is there was no implementation found matching both:
The os
module does not exist at that path, and it never should be looking
at that path. If the build is working correctly that module should always
be loaded, via #[cfg]
directives, at a different platform-specific path.
Most likely you will need to select a supported set of features, or port this library to your target platform.
Support for unix
and windows
This crate will use libc
to provide a backend on Unix-like operating
systems, and the win32
API is used on the Windows operating system. These
implementations will be automatically selected at compile time based on the
target_family
cfg-attribute.
These are full featured implementations which use virtual memory to allow users to reserve (frankly) ludicrously-sized arenas.
#![no_std]
support via alloc
alloc::Vec
as backing storage to provide its bump
allocator API over physically backed memory. Though this somewhat defeats
the purpose of the crate, it does allow you to write code and run it
unmodified in resource constrained environments.smp
: enables thread-safe implementations of the allocator
This somewhat defeats the purpose of using this crate, as a bump allocator is meant to be fast, and generally speaking the locks and atomics used to guard the allocator's state are "not fast™", but presumably you know what you're doing.
Also, the author is an idiot, so this implementation is the most likely to have bugs. As such I implore you to consider structuring your program so that they have thread-local arenas and do not need to share them across threads.
However, sometimes, you just wanna fucking Send
it ... I get it.
Get a default (extremely large, virtual) allocation:
// Allocate an extremely large (128GiB) virtual allocation
let mut arena = VmArena::default();
// Create a Vec<u8> inside that allocation
let mut v: Vec<u8, _> = Vec::with_capacity_in(4096, &arena);
// Use it as normal
v.push(1);
v.push(2);
v.push(3);
// NOTE: v must be dropped first, as its backing RawVec borrows the arena.
drop(v);
arena.reset();
Alternatively you can get a fixed-size allocation instead:
// Create a much smaller 4KiB (1 page) allocation
let mut arena = VmArena::with_capacity(1 * 4096);
// Create a Vec<u8> inside that allocation
let mut v: Vec<u8, _> = Vec::with_capacity_in(4096, &arena);
for i in 0..8192 {
v.push((i % 64) as u8);
}
// NOTE: This example will compile, but lead to a runtime OOM panic!
This crate was largely made possible by the following resources:
I would like to thank both Shawn McGrath and Ryan Fleury. Their streams/videos served as inspiration for leaning on the OS virtual memory faculties, as well as for bundling lifetimes together into scoped arenas. (Ryan's Substack in particular has been a great resource for figuring this stuff out.) This is somewhat contrarian to how Rust typically does memory management, but it actually fits quite nicely with the borrow-checker.
The bumpalo crate is a much more feature-rich bump allocator. It also supports growable arenas without requiring OS specific features. The raison d'être for my crate is explicit support for fixed-sized arenas in resource constrained environments. If you do not need that I would strongly suggest you check out their crate instead!
The virt-arena crate is very similar in principle to this one. It
was a great example of how to package this idea into a multi-platform crate.
Their crate is much more likely to be correct (as it lacks the multithreading
capabilities of this one), so if you do not need to move the allocator
between threads or run in a no_std
environment I would suggest you check
out their crate instead!