-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Make rustc use jemalloc through #[global_allocator] #51038
Comments
This is not how it is implemented in Rust AFAIK, but my model coming from C++ would be that:
If there is a If there is no
And that's it? If the functions are present in the binary, they can be optimized through LTO, and if they aren't, the binary must be dynamically linked to something that has them or it won't run. This adds a couple of constraints on the |
That's exactly how it's implemented in Rust: https://github.com/rust-lang/rust/blob/master/src/liballoc/alloc.rs#L25-L38 |
The technical probably here is, yes, libstd is built as a dynamic library for the compiler. This dynamic library, especially on Windows, needs to have all symbols resolved. This means that when we build libstd itself we must choose an allocator. Currently we aren't set up to do two separate builds of libstd, one for an rlib and one for a dylib. So it's a hard technical requirement that the first dylib we compile must have all symbols resolved, and currently that means that it must select an allocator. We may be able to get away without compiling libstd as a dylib and just dealing with rustc, but that runs a high risk of being a breaking change. A possible solution is basically just hacking around everything here in rustc... somehow. Like basically adding hardcoded logic that libstd's dylib links to jemalloc while the rlib explicitly doesn't link to jemalloc (or something like that) |
Does this mean that |
Well on Windows if the global allocator is in a |
Historically the system allocator and jemalloc had different sets of symbols associated with them and we choose "at the last minute" which to route the main allocation symbols to. Nowadays though with In that sense I think this will be possible by building libstd.dylib with a dynamic dependency on these symbols. Ideally we'd do something like include the symbols in libstd.dylib but force all function calls to go through the dynamic linker still. That way we could still load jemalloc but it wouldn't be required. I'm not sure how plausible that is though for all platforms. |
[Do not merge yet] Remove alloc_jemalloc, switch the default global allocator to System Fixes #36963 **Do not merge** yet. This PR by itself is likely to regress rustc performance. The purpose of opening it now is to measure by how much. We’ll likely want to figure out #51038 and land them around the same time.
It just occurred to me that rustc is already not using jemalloc on Windows, so only Unix-like platforms are relevant to this issue. |
I tried the "obvious" patch (on top of #52020): diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 84f7b35d21..c7e9fc77ce 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -33,6 +33,8 @@ extern crate arena;
extern crate getopts;
extern crate graphviz;
extern crate env_logger;
+#[cfg(not(windows))]
+extern crate jemallocator;
#[cfg(unix)]
extern crate libc;
extern crate rustc_rayon as rayon;
@@ -118,6 +120,11 @@ pub mod driver;
pub mod pretty;
mod derive_registrar;
+#[cfg(not(windows))]
+#[cfg(not(stage0))]
+#[global_allocator]
+static A: jemallocator::Jemalloc = jemallocator::Jemalloc;
+
pub mod target_features {
use syntax::ast;
use syntax::symbol::Symbol; It seems to work perfectly on Linux. The executable and every It doesn’t work at all on macOS. The symbols present in various files look similar, but when running under lldb most calls to Based on these observation I supposed that current versions of rustc might have the same problem because the symbol and linking setup is pretty much the same. Maybe rustc on macOS doesn’t actually use liballoc_jemalloc? But somehow that’s not the case, and |
jemalloc itself hooks up the system allocator on osx, so even if rustc ends up using malloc, it ends up using jemalloc. |
@SimonSapin hm while it may work on Linux all dynamic libraries having I like @glandium's idea of just having jemalloc linked in on OSX to implement the malloc/free symbols with jemalloc. For our tier 1 platforms that just leaves us figuring out Linux as we're not using jemalloc on Windows. For Linux I'm not really sure what the best option is here. I'd love to get to a point where we can simplify how the allocator symbols work out (avoid redirecting shims) and perhaps just explicitly leverage the dynamic linker shenanigans to get the job done. We just need to be careful here because it can in theory affect stable programs compiled against the libstd dynamic library, but I can't imagine there are many of those in existence... |
I agree, but isn’t this setup already the same today? |
@SimonSapin ah indeed true! I think this is a bug though right now in that |
@SimonSapin oh so here's an idea: One possibility would be to create something like a That way libstd's dll would default to the system allocator while librustc's "libstd" would link to jemalloc. I think that'd do the trick? That way we don't have to worry about duplicate symbols and such. |
How would proc-macro crates fit into this? They’re compiled as dynamic libraries loaded in the same process as rustc, right? |
Indeed yeah, but they currently link to libsyntax which is what defines the allocator, and in the future we can just make sure that the proc-macro crate type uses the same allocator as rustc (and/or the same set of runtime libraries) |
I'm gonna try to consolidate allocator and jemalloc/rustc related issues into #36963 as I think this is all basically enabled by one PR which would solve that issue. I'll be updating the OP there soon too |
Once the
#[global_allocator]
attribute and theGlobalAlloc
trait are stable (#49668), we plan to make the system allocator the default for executables instead of jemalloc, and remove jemalloc from the standard library: #36963 / #27389.Presumably, we want rustc to keep using jemalloc since it often performs better, for rustc’s typical workload. Like other programs, it can do so using
#[global_allocator]
and the jemallocator crate or similar. (And make jemalloc symbols be unprefixed so that they get picked up by LLVM too, but I don’t forsee a difficulty adding a Cargo feature tojemallocator
for this.)However, per #45966 (comment) this might not work because rustc itself is compiled with
-C prefer-dynamic
and links to the standard library dynamically.@alexcrichton, are
-C prefer-dynamic
and#[global_allocator]
fundamentally incompatible or is this something we can fix? Is it possible to make rustc not use-C prefer-dynamic
?CC @gnzlbg, @rust-lang/compiler
The text was updated successfully, but these errors were encountered: