From 07f5c659c99312a552e8da74a1e609885b25fecd Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 5 Nov 2014 19:48:39 -0500 Subject: [PATCH] use jemalloc's default prefix By default, jemalloc only uses a prefix on OS X, iOS and Windows where attempting to replace the platform allocator is broken. The lack of a prefix allows jemalloc to override the weak symbols from the C standard library to replace the system allocator. This results in a performance improvement for memory allocation in C along with reduced fragmentation. For example, the time spent on LLVM passes in the Rust compiler on Linux is cut by 10% and peak memory usage is reduced by 15%. Even on platforms like FreeBSD where jemalloc is the system allocator, this eliminates the inevitable external fragmentation and performance hit caused by using two general purpose allocators. Closes #18676 --- mk/rt.mk | 2 +- src/liballoc/heap.rs | 49 +++++++++++++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/mk/rt.mk b/mk/rt.mk index 7204808c30a3b..81f892e9970f2 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -175,7 +175,7 @@ JEMALLOC_LOCAL_$(1) := $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1 $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS) @$$(call E, make: jemalloc) cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \ - $$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \ + $$(JEMALLOC_ARGS_$(1)) $(CFG_JEMALLOC_FLAGS) \ --build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \ CC="$$(CC_$(1))" \ AR="$$(AR_$(1))" \ diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 579f47ee87466..b21b681c8cd4d 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -135,16 +135,37 @@ mod imp { #[cfg(not(test))] extern {} + #[cfg(all(not(target_os = "ios"), not(target_os = "macos"), not(target_os = "windows")))] extern { - fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void; - fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; - fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; - fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); - fn je_nallocx(size: size_t, flags: c_int) -> size_t; - fn je_malloc_stats_print(write_cb: Option *mut c_void; + fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; + fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; + fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); + fn nallocx(size: size_t, flags: c_int) -> size_t; + fn malloc_stats_print(write_cb: Option, - cbopaque: *mut c_void, - opts: *const c_char); + cbopaque: *mut c_void, + opts: *const c_char); + } + + // jemalloc uses a prefix on Darwin and Windows as a workaround for linking deficiencies + #[cfg(any(target_os = "ios", target_os = "macos", target_os = "windows"))] + extern { + #[link_name = "je_mallocx"] + fn mallocx(size: size_t, flags: c_int) -> *mut c_void; + #[link_name = "je_rallocx"] + fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; + #[link_name = "je_xallocx"] + fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; + #[link_name = "je_sdallocx"] + fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); + #[link_name = "je_nallocx"] + fn nallocx(size: size_t, flags: c_int) -> size_t; + #[link_name = "je_malloc_stats_print"] + fn malloc_stats_print(write_cb: Option, + cbopaque: *mut c_void, + opts: *const c_char); } // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough @@ -164,37 +185,37 @@ mod imp { #[inline] pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { let flags = align_to_flags(align); - je_mallocx(size as size_t, flags) as *mut u8 + mallocx(size as size_t, flags) as *mut u8 } #[inline] pub unsafe fn reallocate(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> *mut u8 { let flags = align_to_flags(align); - je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 + rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 } #[inline] pub unsafe fn reallocate_inplace(ptr: *mut u8, _old_size: uint, size: uint, align: uint) -> uint { let flags = align_to_flags(align); - je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint + xallocx(ptr as *mut c_void, size as size_t, 0, flags) as uint } #[inline] pub unsafe fn deallocate(ptr: *mut u8, old_size: uint, align: uint) { let flags = align_to_flags(align); - je_sdallocx(ptr as *mut c_void, old_size as size_t, flags) + sdallocx(ptr as *mut c_void, old_size as size_t, flags) } #[inline] pub fn usable_size(size: uint, align: uint) -> uint { let flags = align_to_flags(align); - unsafe { je_nallocx(size as size_t, flags) as uint } + unsafe { nallocx(size as size_t, flags) as uint } } pub fn stats_print() { unsafe { - je_malloc_stats_print(None, null_mut(), null()) + malloc_stats_print(None, null_mut(), null()) } } }