-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
liballoc_system without #[global_allocator] uses jemalloc #45966
Comments
@alexcrichton wrote #46117 (comment)
Do you mean impossible while also making LLVM use jemalloc? If we revert (relevant parts of) #31460 and go back to always compiling jemalloc with |
Prefixing jemalloc symbols would resolve this issue, but I would argue that would be a net negative. It's not great to have two competing allocators both running at the same time in a single process. As long as alloc_jemalloc/jemallocator/whatever is configured to have non-prefixed symbols, LLVM will continue to use it AFAIK. |
@SimonSapin ah yeah sorry what I meant was we could indeed prefix the symbols but the intention is to get LLVM to use jemalloc (as it makes it ~10% faster historically). I think our long term plan is to remove jemalloc from libtsd but leave it in the compiler, so rustc itself will still use jemalloc but Rust programs by default will not. |
If you really want to talk to specifically glibc malloc, you can link to |
@alexcrichton Right, I think that split between rustc and std is probably the best eventual outcome. @sfackler Interesting. I think we still want |
I can see that point. But then we should not be providing APIs that pretend to do this, while they actually do not. |
TL;DR: let’s switch rustc to unprefixed jemallocator and restore symbol prefixes in alloc_jemalloc now? So, we’re discussing a number of desirable but apparently competing points. I think we can have our cake and eat it too. I’m gonna name them to untangle everything without repeating lengthy phrases over and over.
Currently we have D and E on some platforms since There’s a number of changes we can make. These are not blocked as far as I can tell:
This is blocked on API design decisions:
With 1 alone we gain F, but lose D and E. With 2 alone we gain B and F, but lose A, D, and E. Which of A or B is more desirable (if we have to choose) is debatable. Adding 5 restores A. #33082 (comment) suggests that doing 2 is planned, but not until until 5 is solved (presumably to avoid losing A). At that point we’ll likely also want to avoid losing D (or E). Doing 3 and 4 seems to be to be the easiest way to achieve that. However we don’t need to wait for 5 to be stabilized before doing 3 or 4. So I suggest doing 3, 4, then 1 now-ish. Both in order to fix F, and to be ready to do 2 later when 5 is unblocked. The only point we would temporarily lose is E for stable users. @alexcrichton, @sfackler, what do you think? |
Seems plausible to me! I'm remembering now though that this probably won't work unfortunately. The standard library is created as a dynamic library which currently fixes the allocator to jemalloc ( |
Any mention of "use jemallocator" above implies selecting it with |
Er yes I think I understand what you're advocating for, and it sounds like a great plan. What I mean is that if you do it you'll get a compile time error and it will fail to compile. |
I don’t understand what error that would be. |
Er yes that's what I mean by "fixing the allocator" and "required to get fixed", it's a bit obscure... Turns out it's not a compile time error (but it should be right now) but you can observe the behavior with: #![feature(global_allocator, allocator_api)]
use std::heap::*;
#[global_allocator]
static A: B = B;
struct B;
static mut HIT: bool = false;
unsafe impl<'a> Alloc for &'a B {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
HIT = true;
System.alloc(layout)
}
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
HIT = true;
System.dealloc(ptr, layout)
}
}
fn main() {
println!("hello!");
assert!(unsafe { HIT });
} That program "accidentally" succeeds on Linux due to how the dynamic linker works but it fails on Windows where the dynamic linker works differently. |
Er, when compiling that program with |
This is a pretty old issue now and I think is something we're probably not going to change to preserve performance of rustc, so I'm going to close this in favor of #36963 where we'll intentionally be routing |
@alexcrichton Just to be clear, it would still be wrong if outside the compiler, calling |
@RalfJung it's not really wrong per se in the sense that this is how jemalloc/Linux are designed. The "system allocator" on Linux isn't glibc malloc but rather the This is also intentional behavior that we desired on OSX/Linux because we want LLVM's usage of |
It’s not wrong for |
This was found by @RalfJung in #45955.
alloc_system::System::alloc
callslibc::malloc
which is defined as:When
#[global_allocator]
is not used, the current default for executables isalloc_jemalloc
, which links jemalloc as configured insrc/liballoc_jemalloc/build.rs
. On most platforms, this is without--with-jemalloc-prefix
, which causes jemalloc to define an unprefixedmalloc
symbol that "overrides" libc’s and ends up being used byalloc_system
.So
alloc_system
doesn’t do what the name suggests, in this situation.Like https://github.com/alexcrichton/jemallocator/issues/19 this problem will disappear when
alloc_jemalloc
is eventually removed, but in the meantimealloc_system
doesn’t always do what the name says it does.We stopped prefixing jemalloc symbols in #31460 in order to make LLVM use them. Could we perhaps only do this when compiling a compiler? Or perhaps the compiler could switch to using the
jemallocator
crate, which would gain a Cargo feature flag to disable prefixing? It would do something like that anyway to keep that LLVM+jemalloc benefit whenalloc_jemalloc
is removed and the default for executables is changed toalloc_system
.CC @alexcrichton
The text was updated successfully, but these errors were encountered: