Tracking issue for allocation APIs #27700
Description
Current status
Final incarnation of std::heap is being proposed in rust-lang/rfcs#1974, hopefully for stabilization thereafter.
Open questions for stabilization are:
-
Is it required to deallocate with the exact size that you allocate with? With the
usable_sizebusiness we may wish to allow, for example, that you if you allocate with(size, align)you must deallocate with a size somewhere in the range ofsize...usable_size(size, align). It appears that jemalloc is totally ok with this (doesn't require you to deallocate with a precisesizeyou allocate with) and this would also allowVecto naturally take advantage of the excess capacity jemalloc gives it when it does an allocation. (although actually doing this is also somewhat orthogonal to this decision, we're just empoweringVec). So far @gankro has most of the thoughts on this. -
Is it required to deallocate with the exact
alignthat you allocate with? Concerns have been raised that allocatores like jemalloc don't require this, and it's difficult to envision an allocator that does require this. (more discussion). @ruuda and @rkruppe look like they've got the most thoughts so far on this.
Original report
This is a tracking issue for the unstable APIs related to allocation. Today this encompasses:
allocheap_apioom
This largely involves just dealing with the stabilization of liballoc itself, but it needs to address issues such as:
- Are we willing to stabilize the exact interface of the allocation API as-is today?
- Do we want to stabilize custom allocators?
- Do we want to stabilize a standalone allocation library,
liballoc? - Should
oombe a generally available piece of functionality, and should it be pluggable?
This will likely take a good deal of work to stabilize, and this may be done piecemeal, but this issue should serve as a location for tracking at least these unstable features.
Activity
alexcrichton commentedon Aug 13, 2015
cc @pnkfelix
SimonSapin commentedon Jan 5, 2016
It’s already possible to indirectly use
allocateanddeallocatein stable Rust:Any future GC support (mentioned in the
#[unstable(feature="heap_api"))message) will need to deal with this.While this hack has the merit of existing (and enabling many libraries to making themselves available on stable Rust),
Rc<str>where a reference count is in a header next to (before) that bytes that make up a string. The header needs to be memory-aligned, but the amount of bytes is arbitrary. Tendril ends up calculating the next multiple ofsize_of::<Header>in order to find out what capacity ofVec<Header>to allocate for a given number of bytes.While I’m not attached to the details of the current
alloc::heapAPI, I think it’s important for Stable Rust to have a more straightforward way to allocate/deallocate memory.SimonSapin commentedon Jan 5, 2016
Random idea for a (more rustic?) RAII-based API for
alloc::heap:kamalmarhubi commentedon Mar 17, 2016
this doesn't get you access to the
alignparameter thoughSimonSapin commentedon Mar 17, 2016
Not directly, but you can influence alignment by carefully picking
TinVec::<T>::with_capacity.kamalmarhubi commentedon Mar 18, 2016
@SimonSapin ooh nice! I'd have to read up on alignment rules to figure out if there's a type that would let me align to a page boundary or not, but nice trick :-)
pnkfelix commentedon Mar 18, 2016
@kamalmarhubi This stackoverflow answer is probably the most relevant thing that is actually implemented today: http://stackoverflow.com/questions/32428153/how-can-i-align-a-struct-to-a-specifed-byte-boundary
(Longer term we'll presumably put in something better. The
Allocatortrait I'm proposing hasLayoutobjects to describe blocks of memory that allow one to specify alignment constraints.)kamalmarhubi commentedon Mar 18, 2016
@pnkfelix thanks for the link. Sounds like I'm out of luck for page boundary alignment though! I am also unclear if the allocator would hate me for
SPLICE_F_GIFTpages to the kernel. I should probably set up my own anonymous mapping for this anyway...glaebhoerl commentedon Mar 19, 2016
It took me several seconds to realize that "aligning to a page boundary" actually wasn't a tongue-in-cheek joke about text rendering...
lilith commentedon Aug 29, 2016
I noticed that
set_oom_handlermentions this issue and provides not a scrutinized interface as the reason for instability.Echoing @glandium, my focus is:
Per #33082 (comment), I understand the answer is:
I'm focused on server use cases - particularly those where large allocations are both common and recoverable. I think a strong case for OOM recoverability has been made in several ways.
I would, ideally, like to see
set_oom_handleror another method for making OOM recoverable.Looking at actionable options, I appear to be presented with:
set_oom_handler. What would be most helpful?And last, is this the right place to discuss, or should this be a separate issue?
lilith commentedon Sep 2, 2016
I've seen a lot of push-back about whether Rust should offer graceful handling of malloc failure. A few points that recur:
And a few recurring points about panic-on-OOM specifically:
abortbehavior, having assumed a recoverable behavior as is present in many other languages. Perhaps a poll could measure which behavior (panic vs. abort) is less surprising?catch_panicis used without expectation that an OOM panic is possible. This concern has legs, but would support a strategy to make panic the default - process abort is always going to work, but increasing the scenarios in which OOM panics might trigger unexpected code paths. So#![feature(abort_on_oom)]couldn't cause unexpected behavior (only absence of behavior), while#![feature(panic_on_oom)]could cause unexpected behavior in an improperly usedcatch_panic. Rust seems to favor more conservative/forwards-compatible approaches, soabort_on_oomas opt-in would seem to be consistent with that philosophy.I have not yet found any sound arguments as to why OOM should not panic by default (vs. current behavior - panic sometimes, but usually abort).
Perhaps I should write a rust app that demonstrates how malloc failure isn't what people expect, and link to it here.
lilith commentedon Sep 2, 2016
I am concerned that as
catch_panicwas stabilized a few weeks ago, crates may start using it with false assumptions about panic vs. abort on OOM (currently either can occur, which is actually a good thing - they cannot correctly assume OOM exclusively aborts, although the docs aren't clear about this).As code paths dependent upon this may start appearing, the likelihood of breakage decreases the earlier OOM behavior is changed (or clearly documented to be changing, or documented as changeable).
To present a couple strawmen that, through simplicity, might be faster to stabilize:
Opt-in to Panic
#![feature(panic_on_oom)]- a subset of#![feature(oom)]catch_panicusers.#![feature(oom)]catch_panicand other relevant documentation, to encourage crate authors to support the behavior, for those (potentially theoretical?) crates who depend on certain behavior fromcatch_panic.Out-out of panic
#![feature(abort_on_oom)]- a subset of#![feature(oom)]Would either of these be easier to fast-track for stabilization (compared to stabilizing
allocoroom)?EDIT: Is there concern that libstd may not be robust in the face of panic-on-OOM due to unsafe bits with un-exercised OOM failure states? If so, perhaps this could be opened as an issue for me to work on? With custom allocators this can be pretty straightforward to test.
arielb1 commentedon Sep 4, 2016
@nathanaeljones
OOM always aborts. It's only capacity overflows that panic, which
Vecis required to handle correctly. Other collections may not be as careful.For example,
BTreeMapdoes not guard its allocations with a capacity overflow, and is a fairly complicated bit of code.10 remaining items
SimonSapin commentedon Mar 29, 2017
And of course, before stabilizing:
unsafefunction exactly what invariants callers need to maintain.Gankra commentedon Mar 29, 2017
If we insist on building more ergonomic APIs, I think we should expose the current ones as-is, suffixed with
_rawor something. Just so there's absolutely zero blocker on getting them out, and everyone knows they're using the kinda janky "look it works" one.SimonSapin commentedon Mar 30, 2017
I proposed small changes in passing because that seemed an easy improvement, but I’m not particularly attached to them. And I don’t think they’re worth doubling the API surface. @gankro What’s the value of the
_rawfunctions if the other ones are only slightly different?Gankra commentedon Mar 30, 2017
There is little to know value; I've just seen this API get punted from stabilization time and time again over hemming and hawing over potential improvements, when everyone just needs some way to allocate with a given size and alignment. So basically I'm desperate to do anything it takes to get this landed. I had already been planning to suggest this rename precisely to get them "out of the way" of premium name real-estate.
I personally don't think our lowest level allocation functions should provide any help or do anything on top of the system allocator. This is a critical code path. We should definitely provide higher level abstractions that do the sorts of things you suggest, but the API as it exists should be preserved and pushed out ASAP.
SimonSapin commentedon Mar 30, 2017
Sounds fair enough. I’ve edited my "proposal" message above to skip the changes.
I don’t have an opinion on the rename.
aturon commentedon Apr 25, 2017
Discussed briefly in the libs meeting today; I proposed that we need to get all of the allocator stakeholders together to discuss our plan (in light of @sfackler's RFC, etc).
The goal would be to lay out a definite plan of action for incremental stabilization of pieces of the allocator system, trying to get something stable ASAP.
If you'd like to take part in this discussion, please leave a comment and I'll be in touch.
yorickpeterse commentedon Apr 25, 2017
@aturon I'm happy to share any feedback/thoughts/grumpy remarks/etc.
Gankra commentedon Apr 27, 2017
I'd like to be involved.
alexcrichton commentedon May 19, 2017
Ok! We've now had a chance to get many of the stakeholders together and chat about the current state of affairs. Action items coming out of this moot:
std::heapAPI is poposed in Prepare global allocators for stabilization rfcs#1974 and can likely be stabilized far ahead of the "swap the global allocator" logic proposed in the RFC.So with that in mind hopefully we can aim to start closing out this issue soon!
rolandsteiner commentedon Jun 19, 2017
[I hope this is the right place to ask]
Playing around with aligned allocation using alloc::heap::allocate, I noticed that usable_size() does not steadily increase by a factor of 2 with increasing requests, but instead jumps in reported (effectively allocated?) storage after 2K directly to 16K.
That is, when requesting an allocation just larger than 2K, usable_size() will report 16K, even if 4K or 8K would have sufficed. Is this known or expected?
Playground: https://is.gd/HGhRYR
ssokolow commentedon Jun 19, 2017
@rolandsteiner Have you tried requesting the system allocator to see if that behaviour changes?
...because I know jemalloc rounds allocations up as part of its approach for combatting memory fragmentation in long-running programs.
EDIT: Yep. I just tried adding
alloc_systemto your example and now the allocations match the requests. https://is.gd/ce43nSYou'll have to ask the jemalloc devs what rationale they used to decide against having a 4K or 8K arena.
rolandsteiner commentedon Jun 20, 2017
@ssokolow Thanks for the follow-up! I was mainly puzzled because this behavior is only triggered by the requested alignment, not size (i.e., a 4K or 8K request on a 2K alignment returns a 4K/8K block just fine).
This means, one cannot naively request a single 4K page. But perhaps the playground server runs on a different architecture that uses 16K pages (?).
alexcrichton commentedon Jun 20, 2017
Upon review of the allocator-related tracking issues we actually have quite a lot now! I'm going to close this in favor of #32838 as the stabilization of the
std::heapmodule is now quite likely to use those traits.I'll be copying over some of the points at the top of this tracking issue to that issue as well.