Rulloc

Rulloc (Rust Allocator) is a general purpose memory allocator written in Rust. It implements std::alloc::Allocator and std::alloc::GlobalAlloc traits. All memory is requested from the kernel using mmap syscalls on Linux and VirtualAlloc on Windows. You can run the examples as follows:

bash cargo run --example standalone cargo run --example global cargo run --example buckets cargo run --example aligned

Run the tests:

bash cargo test

Run with Miri:

bash cargo miri test cargo miri run --example standalone cargo miri run --example buckets cargo miri run --example aligned

Global allocator example doesn't work with Miri, see examples/global.rs.

Implementation

I started this project for learning purposes, and I know the best way to make sure you understand something is explaining it to others. So there's plenty of documentation and ASCII diagrams throughout the codebase if you're interested in how memory allocators work internally. Start by reading src/allocator.rs for a quick overview and you'll be redirected to the rest of files through intra-doc links.

Block

If you don't want to scroll through hundreds of lines of code, this is how a memory block looks like:

text +----------------------------+ | pointer to next block | <------+ +----------------------------+ | | pointer to prev block | | +----------------------------+ | | pointer to block region | | +----------------------------+ | Block Header | block size | | +----------------------------+ | | is free flag (1 byte) | | +----------------------------+ | | padding (struct alignment) | <------+ +----------------------------+ | Block content | <------+ | ... | | | ... | | Addressable content | ... | | | ... | <------+ +----------------------------+

Region

All blocks belong to a memory region, which is a contiguous chunk of memory that can store multiple pages. In other words, the size of each region is a multiple of the virtual memory page size on the current platform, and each region contains a linked list of blocks:

text +--------+--------------------------------------------------+ | | +-------+ +-------+ +-------+ +-------+ | | Region | | Block | -> | Block | -> | Block | -> | Block | | | | +-------+ +-------+ +-------+ +-------+ | +--------+--------------------------------------------------+

Bucket

The allocator can be configured at compile time with multiple allocation buckets of different sizes in order to reduce fragmentation. Each bucket stores a linked list of memory regions and a free list, which is basically a linked list of only free blocks:

text Next free block in the free list Next free block +--------------------------------------+ +-----------------------+ | | | | +--------+-----|------------------+ +--------+---|---|-----------------------|-----+ | | +---|---+ +-------+ | | | +-|---|-+ +-------+ +---|---+ | | Region | | Free | -> | Block | | ---> | Region | | Free | -> | Block | -> | Free | | | | +-------+ +-------+ | | | +-------+ +-------+ +-------+ | +--------+------------------------+ ---------+-------------------------------------+

Allocator

And finally, to put it all together, the allocator is an array of buckets:

```text Next Free Block Next Free Block +------------------------------------+ +-----------------------+ | | | | +--------+-------|----------------+ +--------+---|---|-----------------------|-----+ | | +-----|-+ +-------+ | | | +-|---|-+ +-------+ +---|---+ | 0 -> | Region | | Free | -> | Block | | ---> | Region | | Free | -> | Block | -> | Free | | | | +-------+ +-------+ | | | +-------+ +-------+ +-------+ | +--------+------------------------+ +--------+-------------------------------------+

                                          Next Free Block
                             +----------------------------------------+
                             |                                        |
 +--------+------------------|-----+      +--------+------------------|------------------+
 |        | +-------+    +---|---+ |      |        | +-------+    +---|---+    +-------+ |

1 -> | Region | | Block | -> | Free | | ---> | Region | | Block | -> | Free | -> | Block | | | | +-------+ +-------+ | | | +-------+ +-------+ +-------+ | +--------+------------------------+ +--------+-------------------------------------+

..............................................................................................

                                    Next Free Block
                             +---------------------------+
                             |                           |
 +--------+------------------|-----+      +--------+-----|-------------------------------+
 |        | +-------+    +---|---+ |      |        | +---|---+    +-------+    +-------+ |

N -> | Region | | Block | -> | Free | | ---> | Region | | Free | -> | Block | -> | Block | | | | +-------+ +-------+ | | | +-------+ +-------+ +-------+ | +--------+------------------------+ +--------+-------------------------------------+ ```

All these data structures are a little bit more complicated than that, but you'll have to read the source code for further details.

TODO