Skip to content

Factor the slab allocator out of the mesh allocator, and make it generic.#23232

Merged
alice-i-cecile merged 11 commits intobevyengine:mainfrom
pcwalton:factor-out-allocator
Mar 24, 2026
Merged

Factor the slab allocator out of the mesh allocator, and make it generic.#23232
alice-i-cecile merged 11 commits intobevyengine:mainfrom
pcwalton:factor-out-allocator

Conversation

@pcwalton
Copy link
Copy Markdown
Contributor

@pcwalton pcwalton commented Mar 5, 2026

The mesh allocator has grown fairly sophisticated, with an efficient O(1) allocation strategy, the ability to manage heterogeneous slabs, batched allocation and deallocation, and so on. However, it's currently tied to meshes. In order to scale to millions of mesh instances, I want to allocate bins using the same strategy. So, in preparation for these bin slabs, this commit factors out the generic allocation logic in MeshAllocator into a new generic SlabAllocator type.

The refactored slab allocator is driven by a new trait, SlabItem. Implementing SlabItem requires specifying the size of the elements that are to be stored in the slabs, as well as the type of the key used to retrieve those items. A single slab allocator can be directed to manage heterogeneous slabs by implementing the associated SlabItem::Layout type.

This PR also refactors slab allocation and deallocation to be explicitly transactional. This means that users of the allocator no longer need to have special logic to deallocate empty slabs and reallocate slabs that changed in size. To perform batched allocation, code that uses the allocator calls stage_allocation to retrieve an AllocationStage object, calls AllocationStage::allocate repeatedly to perform all necessary allocations, and finally calls commit; slab reallocation happens efficiently under the hood. Likewise, to perform batched deallocation, the client code calls stage_deallocation to create a DeallocationStage object, calls DeallocationStage::free to free all necessary objects, and then calls commit to free slabs that are have become empty.

Along with the forthcoming PR to add SparseBufferVec, this PR is a prerequisite to bin slabs. Moreover, it makes the mesh allocation code considerably cleaner and easier to understand.

generic.

The mesh allocator has grown fairly sophisticated, with an efficient
O(1) allocation strategy, the ability to manage heterogeneous slabs,
batched allocation and deallocation, and so on. However, it's currently
tied to meshes. In order to scale to millions of mesh instances, I want
to allocate bins using the same strategy. So, in preparation for these
bin slabs, this commit factors out the generic allocation logic in
`MeshAllocator` into a new generic `SlabAllocator` type.

The refactored slab allocator is driven by a new trait, `SlabItem`.
Implementing `SlabItem` requires specifying the size of the elements
that are to be stored in the slabs, as well as the type of the key used
to retrieve those items. A single slab allocator can be directed to
manage heterogeneous slabs by implementing the associated
`SlabItem::Layout` type.

This PR also refactors slab allocation and deallocation to be explicitly
transactional. This means that users of the allocator no longer need to
have special logic to deallocate empty slabs and reallocate slabs that
changed in size. To perform batched allocation, code that uses the
allocator calls `stage_allocation` to retrieve an `AllocationStage`
object, calls `AllocationStage::allocate` repeatedly to perform all
necessary allocations, and finally calls `commit`; slab reallocation
happens efficiently under the hood. Likewise, to perform batched
deallocation, the client code calls `stage_deallocation` to create a
`DeallocationStage` object, calls `DeallocationStage::free` to free all
necessary objects, and then calls `commit` to free slabs that are have
become empty.

Along with the forthcoming PR to add `SparseBufferVec`, this PR is a
prerequisite to bin slabs. Moreover, it makes the mesh allocation code
considerably cleaner and easier to understand.
@pcwalton pcwalton requested review from atlv24 and tychedelia March 5, 2026 17:53
@pcwalton pcwalton added the A-Rendering Drawing game state to the screen label Mar 5, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Rendering Mar 5, 2026
@pcwalton pcwalton added C-Code-Quality A section of code that is hard to understand or change S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 5, 2026
Comment thread crates/bevy_render/src/mesh/allocator.rs
Copy link
Copy Markdown
Contributor

@atlv24 atlv24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice cleanup

Copy link
Copy Markdown
Contributor

@IceSentry IceSentry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (assuming @tychedelia comment is addressed and conflicts are fixed)

@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Mar 22, 2026
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 24, 2026
Merged via the queue into bevyengine:main with commit ae7af25 Mar 24, 2026
38 checks passed
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in Rendering Mar 24, 2026
splo pushed a commit to splo/bevy that referenced this pull request Mar 31, 2026
…ric. (bevyengine#23232)

The mesh allocator has grown fairly sophisticated, with an efficient
O(1) allocation strategy, the ability to manage heterogeneous slabs,
batched allocation and deallocation, and so on. However, it's currently
tied to meshes. In order to scale to millions of mesh instances, I want
to allocate bins using the same strategy. So, in preparation for these
bin slabs, this commit factors out the generic allocation logic in
`MeshAllocator` into a new generic `SlabAllocator` type.

The refactored slab allocator is driven by a new trait, `SlabItem`.
Implementing `SlabItem` requires specifying the size of the elements
that are to be stored in the slabs, as well as the type of the key used
to retrieve those items. A single slab allocator can be directed to
manage heterogeneous slabs by implementing the associated
`SlabItem::Layout` type.

This PR also refactors slab allocation and deallocation to be explicitly
transactional. This means that users of the allocator no longer need to
have special logic to deallocate empty slabs and reallocate slabs that
changed in size. To perform batched allocation, code that uses the
allocator calls `stage_allocation` to retrieve an `AllocationStage`
object, calls `AllocationStage::allocate` repeatedly to perform all
necessary allocations, and finally calls `commit`; slab reallocation
happens efficiently under the hood. Likewise, to perform batched
deallocation, the client code calls `stage_deallocation` to create a
`DeallocationStage` object, calls `DeallocationStage::free` to free all
necessary objects, and then calls `commit` to free slabs that are have
become empty.

Along with the forthcoming PR to add `SparseBufferVec`, this PR is a
prerequisite to bin slabs. Moreover, it makes the mesh allocation code
considerably cleaner and easier to understand.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Code-Quality A section of code that is hard to understand or change S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants