Skip to content
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

LLVM doesn't know about jemalloc #22159

Closed
XMPPwocky opened this issue Feb 10, 2015 · 11 comments · Fixed by #22526
Closed

LLVM doesn't know about jemalloc #22159

XMPPwocky opened this issue Feb 10, 2015 · 11 comments · Fixed by #22526
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. I-slow Issue: Problems and improvements with respect to performance of generated code.

Comments

@XMPPwocky
Copy link
Contributor

LLVM can remove "dead" calls to malloc() (where the return value is ignored, or immediately free()-d (possibly after being compared with NULL)). However, this is basically hardcoded to the "malloc" symbol (and "free", etc.); it is not aware of jemalloc (specifically je_mallocx and je_sdallocx), which Rust uses.

LLVM is very good at removing temporary allocations, as it turns out:

extern crate libc;
extern crate test;

fn main() {

unsafe {
    // totally dead (and a memory leak)
    // produces no calls to libc malloc
    let _ = libc::malloc(4);

    // freed immediately, no allocations
    libc::free(libc::malloc(4));

    // allocated, used to store something temporarily, then freed
    // still no allocations!
    let x = libc::malloc(std::mem::size_of::<i32>() as libc::size_t);
    assert!(!x.is_null());
    *(x as *mut i32) = 42i32;
    let y = *(x as *mut i32);
    libc::free(x);
    test::black_box(y);
}

}

will not call malloc or free (at -O2).

On the other hand, even the most trivial allocation using liballoc...

fn main() {
    let _ = Box::new(42i32);
}

will invoke je_mallocx and je_sdallocx, even at -O3.

/cc @dotdash

@bstrie
Copy link
Contributor

bstrie commented Feb 11, 2015

I feel like we must have opened an issue for this at some point, but a cursory search doesn't show one.

@bstrie bstrie added I-slow Issue: Problems and improvements with respect to performance of generated code. A-an-interesting-project labels Feb 11, 2015
@bstrie
Copy link
Contributor

bstrie commented Feb 11, 2015

I believe that past discussions of this behavior have involved making jemalloc pretend to be malloc in order to trigger the optimization, but here are we proposing to change LLVM itself?

@XMPPwocky
Copy link
Contributor Author

Apparently Rust already uses a few patches on LLVM; adding another one is probably not that bad.

I think the best way for this to be handled is for there to be some way to indicate "malloc-y stuff" to LLVM; currently, LLVM is just hardcoded. The easiest change would just be replacing "malloc" with "je_mallocx", and "free" with "je_sdallocx", but removing the hardcoding entirely (and contributing that back to LLVM upstream) is probably ideal.

It's arguable that this is actually LLVM's issue, but because we are already not using "stock" LLVM, it may be worth it to diverge a little further from LLVM master.

I'm not sure how jemalloc could pretend to be malloc, because the APIs are different; from what I saw of LLVM's code, it checks both the function name and the signature. Any wins from better optimization here are unlikely to be worth giving up sized deallocation and alignment, for example.

@steveklabnik
Copy link
Member

Apparently Rust already uses a few patches on LLVM; adding another one is probably not that bad.

Most (maybe all?) of them are performance related these days, and we try to move them upstream. Building with standard LLVM will be important for things like packaging Rust.

@alexchandel
Copy link

This is significant, since for a basic hello world program,

fn main() {
    let _ = Box::new(42i32);
}

jemalloc consumes approximately 70% of the resulting executable (on x86_64 OS X).

@XMPPwocky
Copy link
Contributor Author

@steveklabnik This is also a performance-related change, and should be backwards- and forwards- compatible (can only tell it's there by examining performance or jemalloc instrumentation; otherwise you can remove it or add it and nobody's the wiser.).

@steveklabnik steveklabnik added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Feb 13, 2015
@XMPPwocky
Copy link
Contributor Author

This would fix many of the issues caused by #13996 , as allocation functions are automatically marked noalias.

@XMPPwocky
Copy link
Contributor Author

The "quick and dirty" fix for this: https://gist.github.com/XMPPwocky/4bdb29e142d235899867

@alexchandel
Copy link

@XMPPwocky Please put this in a PR! The fix is so simple, we can safely apply it to our branch. It solves the here-and-now problem, it doesn't require us to address custom allocators first, and it doesn't fundamentally change the language—just the optimization capabilities of our implementation. It can even be applied to a future stable release like LLVM 3.6, should that happen before Rust 1.0. True, the librustc available from rust-lang.org wouldn't be statically linked against an unmodified, stable release of LLVM, but the gains speak for themselves.

@XMPPwocky
Copy link
Contributor Author

rust-lang/llvm#37 has been merged.

@dotdash
Copy link
Contributor

dotdash commented Feb 18, 2015

JFYI, I'll make a PR to update LLVM to 3.6 RC4 once it's tagged (probably tomorrow). That will include the patch from rust-lang/llvm#37, no need for a dedicated PR to update LLVM just for this.

dotdash added a commit to dotdash/rust that referenced this issue Feb 19, 2015
Manishearth added a commit to Manishearth/rust that referenced this issue Feb 20, 2015
dotdash added a commit to dotdash/rust that referenced this issue Feb 21, 2015
bors added a commit that referenced this issue Feb 21, 2015
bors added a commit that referenced this issue Feb 22, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. I-slow Issue: Problems and improvements with respect to performance of generated code.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants