Skip to content

Pre-proposal: Type-aware allocators #27

Closed
@Avi-D-coder

Description

@Avi-D-coder

Currently this use case is supported for the Alloc trait, but not GlobalAlloc.

As discussed in #18 generic methods (I.e{alloc,dealloc}_one) cannot be used to support this use case in GlobalAlloc and maybe removed from Alloc. An alternative that is consistent across both methods is needed.

Type information is necessary for ECS allocators, typed Pool/Slab allocators, many GC, STM optimizations, and describable for heap profilers, and exotic heuristic guided allocators as a significant source of free information.

  • Today there are many slab and generational indexed allocators. They are incompatible with box, std, and each other. They all provide some version of the following: allocation and deallocation of T: Sized, indexing/dereferencing and usually iterating over Ts.
    By passing unsized allocations to an underlying or global allocator. They could easily implement the Alloc trait to take advantage of standard collections and boxes, but to do this they require knowing more than just Layout, they require TypeId.

  • I am working on a allocator for use a with both Alloc and GlobalAlloc that requires typed pools of Sized T to support pause free optional GC. Without a method of differentiating allocations and deallocations that share the same Layout, but different types my use case is impossible.

In order to support all the mentioned use cases TypeId needs to always be provided to allocations and deallocations of Sized Types and N Sized Types . Layout looks like the best place to ensure TypeId is always passed.

Layout would have type_id_ added and TypeId implementation would be changed to NonZeroU64. type_id_ would not be considered by Eq, so as not to break compatibility.

pub struct Layout {
    size_: usize,
    align_: NonZeroUsize,
    type_id_: Option<TypeId>
}

Drawbacks

Adding another field to Layout could have a tiny performance cost.

alternatives

Originally I had wanted a separate set of functions for this use case analogous to Alloc::{alloc,dealloc}_array and Alloc::{alloc,dealloc}_one (like below), but this allows for human error (E.g calling the normal unsized set of functions when you have a sized type).

alloc_typed(&mut self, layout: Layout, _: TypeId) -> Result<NonNull<u8>, AllocErr> {
  alloc(self, layout)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    DiscussionIssues containing a specific idea, which needs to be discussed in the WG

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions