Skip to content

Proposal: checkpoints in FixedBufferAllocator and ArenaAllocator #24701

@suleyth

Description

@suleyth

A checkpoint, also called "temporary memory" or I think sub-arenas is a concept in linear allocators that helps you free everything in a specific scope. Essentially it just stores the end_index when it was created and then restores it, considering everything allocated in-between as "freed". As an example:

const checkpoint = fba.checkpoint();

fba.alloc(...);
fba.alloc(...);
fba.alloc(...);

fba.resetTo(checkpoint); // the three previous allocations are considered "free", but this doesn't reset the entire buffer

Some use cases for this would be:

  • Quick allocations that only need to live for a single scope. This allows you to save memory for more long-lived things while still enjoying the very fast allocation and freeing of an fba or an arena.
  • Allows reusing most of the buffer while retaining some long-lived allocations at the beginning (for example storing some global data, then storing different levels of a game, that get swapped by resetting to the checkpoint)
  • Helps keeping the memory usage low, which is useful in fba's case, given they have an upper bound

Adding this to FixedBufferAllocator is extremely trivial. You don't in theory even need a wrapper for it because there's no private fields in Zig, but adding standard library support for this may be neat.

Adding this to ArenaAllocator however is a bit more involved and hard to get right, so I would say at least this one definitely needs standard library involvement. In theory you would need the checkpoint to store the current last memory block, and then resetTo would have to free/empty all blocks allocated since the checkpoint by traversing the linked list.

I'm willing to PR this if the proposal gets accepted! Thanks for reading.

Quick note

It's possible to implement something like this already with an arena by allocating a buffer and using an fba on it. At the end of the temporary memory scope, the arena can free the buffer because it's the last allocation. However I think it's worth it to implement it like I mentioned above, since this solution feels a bit hacky and goes against the reasons to use an arena instead of an fba in the first place (to have no upper bound and to reduce unused memory)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions