-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pre-proposal: Type-aware allocators #27
Comments
I think it would be better to add a new trait for type aware allocators, such as trait TypedAlloc<T> {
fn alloc_array(n: usize) -> Result<NonNull<[T]>, AllocErr>;
unsafe fn dealloc_array(ptr: NonNull<[T]>);
fn alloc_one() -> Result<NonNull<T>, AllocErr>;
unsafe fn dealloc_one(ptr: NonNull<T>);
// maybe more ...
} |
@KrishnaSannasi That's the API we have today in the Alloc trait see #18 (comment) for why generic can't be in Also making a separate trait without the ability to handle multiple or unsized types mean that standard collections could never use such a trait. |
Ok, but I don't think we can make any typed allocator a global allocator. So this shouldn't matter, right?
I was proposing a simple solution, we could change it or make it more sophisticated to better handle the standard collections' use case. Now that I've thought about it a bit more, we could change trait TypedAlloc<T: ?Sized> {
type Meta;
fn alloc(meta: Self::Meta) -> Result<NonNull<T>, AllocErr>;
unsafe fn dealloc(ptr: NonNull<T>);
// maybe more ...
} Where we could use it like this, playground. I think this should support the use cases for standard library types well enough. |
@KrishnaSannasi My proposal passes type info to Global Allocators and Even if we were to exclude the |
@Avi-D-coder Oh, I misunderstood. Thanks for clarifying. |
FWIW, both solutions aren't really incompatible with each other (we could have both). While currently That is, a |
@gnzlbg your right they are compatible, but this proposal is specifically about always passing type information from boxing one or
|
Note that another recent RFC is proposing to allow transmutes between |
@comex That would forbid |
Currently This proposal adds another two fields to I'm not sure of what the performance implications of that are, but would rather not do it I think. |
@gnzlbg The proposal includes changing
Do any calling convention besides I would also suspect LTO to remove the unused argument for allocators that don't use This is all likely moot, since rust-lang/rust#26494 implies |
@comex If that RFC goes through, type-aware allocators will just have to account for deallocation not having an accurate |
No, this isn't possible. The arguments are always passed according to the calling convention, and the global allocator functions cannot, in general, be inlined. You can, e.g., change the allocator at run-time, using
I thought actually that most ABIs make this restriction for return types (not arguments), and we have a couple of APIs that return Layouts IIRC. |
We pass scalars and scalar pairs in registers, and have two separate ABI classes for those in the Rust ABI ( |
@gnzlbg That could be a problem. I'll have to benchmark this. |
I think you are focusing too much on how to implement something, and not on making a case for this feature. To me at least it is very unclear:
I see many fundamental problems with the approach. First:
This means that the use cases that rely on accurate type information cannot really work, and that So if this is a hint, would such a hint be useful? No major allocator supports this (malloc, jemalloc, mimalloc, tcmalloc, weealloc, hurd, ...). Some of the I can imagine that one can build an allocator that exploits |
I should have real code to publish, in the next couple of weeks. I'll publish a detailed write up with it including API requirements, trade-offs, benchmarks, etc... |
What's unclear to me is why that should be provided via |
I no longer believe passing |
Currently this use case is supported for the
Alloc
trait, but notGlobalAlloc
.As discussed in #18 generic methods (I.e
{alloc,dealloc}_one
) cannot be used to support this use case inGlobalAlloc
and maybe removed fromAlloc
. 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 overT
s.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 requireTypeId
.I am working on a allocator for use a with both
Alloc
andGlobalAlloc
that requires typed pools ofSized
T
to support pause free optional GC. Without a method of differentiating allocations and deallocations that share the sameLayout
, 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 ofSized
Types andN
Sized
Types . Layout looks like the best place to ensureTypeId
is always passed.Layout
would havetype_id_
added andTypeId
implementation would be changed toNonZeroU64
.type_id_
would not be considered byEq
, so as not to break compatibility.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
andAlloc::{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).The text was updated successfully, but these errors were encountered: