- 
                Notifications
    You must be signed in to change notification settings 
- Fork 152
Native libraries use mimalloc as global allocator #1249
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
          
     Merged
      
      
    
  
     Merged
                    Changes from all commits
      Commits
    
    
            Show all changes
          
          
            14 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      8b09156
              
                Native libraries use mimalloc as global allocator
              
              
                idavis 9d669d6
              
                Implementing mimalloc-sys crate and dynamic mimalloc compilation
              
              
                idavis 8aba7d2
              
                Remove ninja dep
              
              
                idavis 10933e4
              
                Static linking crt
              
              
                idavis 9618cda
              
                Adding some verbosity and clean path
              
              
                idavis b0d9542
              
                Seeing if windows crash is due to 2.x
              
              
                idavis 86facfe
              
                Trying more windows flags.
              
              
                idavis 21e1eb5
              
                Simplifying compilation.
              
              
                idavis db58fff
              
                Optimizing perf and setting up windows crt
              
              
                idavis a8a4dcd
              
                Updating building instructions
              
              
                idavis 3f46b50
              
                Cleaning up
              
              
                idavis 516b407
              
                Move allocator asignement into macro.
              
              
                idavis 625fadc
              
                Fix typo and add prereq check for cmake
              
              
                idavis d73a711
              
                Updating dev container to support c compilation.
              
              
                idavis File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
|  | @@ -15,3 +15,5 @@ __pycache__/ | |
| /fuzz/artifacts | ||
| /fuzz/coverage | ||
| /fuzz/Cargo.lock | ||
| .mypy_cache/ | ||
| .pytest_cache/ | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
      
      Oops, something went wrong.
      
    
  
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| [package] | ||
|         
                  idavis marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| name = "allocator" | ||
| authors.workspace = true | ||
| homepage.workspace = true | ||
| repository.workspace = true | ||
| edition.workspace = true | ||
| license.workspace = true | ||
| version.workspace = true | ||
|  | ||
| [dependencies] | ||
| mimalloc-sys = { path = "./mimalloc-sys" } | ||
|  | ||
| [lints] | ||
| workspace = true | ||
|  | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|  | ||
| cmake_minimum_required(VERSION 3.10.0) | ||
|  | ||
|  | ||
| project(allocator_external) | ||
| include(ExternalProject) | ||
|  | ||
| ExternalProject_Add(mimalloc | ||
| GIT_REPOSITORY https://github.com/microsoft/mimalloc.git | ||
| GIT_TAG $ENV{ALLOCATOR_MIMALLOC_TAG} | ||
| GIT_SHALLOW TRUE | ||
| GIT_PROGRESS TRUE | ||
| CONFIGURE_COMMAND "" | ||
|         
                  idavis marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| BUILD_COMMAND "" | ||
| INSTALL_COMMAND "" | ||
| TEST_COMMAND "" | ||
| USES_TERMINAL_DOWNLOAD TRUE | ||
| ) | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| [package] | ||
| name = "mimalloc-sys" | ||
| build = "build.rs" | ||
| links = "mimalloc" | ||
| authors.workspace = true | ||
| homepage.workspace = true | ||
| repository.workspace = true | ||
| edition.workspace = true | ||
| license.workspace = true | ||
| version.workspace = true | ||
|  | ||
| [dependencies] | ||
|  | ||
| [lints] | ||
| workspace = true | ||
|  | ||
| [build-dependencies] | ||
| cmake = "0.1" | ||
| cc = "1.0" | ||
|         
                  idavis marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
|  | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|  | ||
| use std::boxed::Box; | ||
| use std::env; | ||
| use std::error::Error; | ||
| use std::fs; | ||
| use std::path::{Path, PathBuf}; | ||
|  | ||
| use cmake::Config; | ||
|  | ||
| // 1.8.2 | ||
| //static ALLOCATOR_MIMALLOC_TAG: &str = "b66e3214d8a104669c2ec05ae91ebc26a8f5ab78"; | ||
| // 2.1.2 | ||
| static ALLOCATOR_MIMALLOC_TAG: &str = "43ce4bd7fd34bcc730c1c7471c99995597415488"; | ||
|          | ||
|  | ||
| fn main() -> Result<(), Box<dyn Error>> { | ||
| let dst = download_mimalloc()?; | ||
| compile_mimalloc(&dst); | ||
| println!("cargo:rerun-if-changed=build.rs"); | ||
| println!("cargo:rerun-if-changed=CMakeLists.txt"); | ||
| Ok(()) | ||
| } | ||
|  | ||
| // Compile mimalloc source code and link it to the crate. | ||
| // The cc crate is used to compile the source code into a static library. | ||
| // The cmake crate is used to download the source code and stage it in the build directory. | ||
| // We don't use the cmake crate to compile the source code because the mimalloc build system | ||
| // loads extra libraries, changes the name and path around, and does other things that are | ||
| // difficult to handle. The cc crate is much simpler and more predictable. | ||
| fn compile_mimalloc(dst: &Path) { | ||
| let src_dir = dst | ||
| .join("build") | ||
| .join("mimalloc-prefix") | ||
| .join("src") | ||
| .join("mimalloc"); | ||
|  | ||
| let mut build = cc::Build::new(); | ||
|  | ||
| build.include(src_dir.join("include")); | ||
| build.include(src_dir.join("src")); | ||
| build.file(src_dir.join("src/static.c")); | ||
|  | ||
| if build.get_compiler().is_like_msvc() { | ||
| build.cpp(true); | ||
| build.static_crt(true); | ||
| } | ||
| // turn off debug mode | ||
| build.define("MI_DEBUG", "0"); | ||
|  | ||
| // turning on optimizations doesn't seem to make a difference | ||
| //build.opt_level(3); | ||
|  | ||
| build.compile("mimalloc"); | ||
|  | ||
| println!( | ||
| "cargo:rustc-link-search=native={}", | ||
| dst.join("lib").display() | ||
| ); | ||
| println!("cargo:rustc-link-lib=static=mimalloc"); | ||
| } | ||
|  | ||
| // Use cmake to download mimalloc source code and stage | ||
| // it in the build directory. | ||
| fn download_mimalloc() -> Result<PathBuf, Box<dyn Error>> { | ||
| let build_dir = get_build_dir()?; | ||
| let mut config = Config::new(build_dir); | ||
|  | ||
| config | ||
| .no_build_target(true) | ||
| .env("ALLOCATOR_MIMALLOC_TAG", ALLOCATOR_MIMALLOC_TAG) | ||
| .very_verbose(true); | ||
|  | ||
| let dst = config.build(); | ||
|  | ||
| Ok(dst) | ||
| } | ||
|  | ||
| fn get_build_dir() -> Result<PathBuf, Box<dyn Error>> { | ||
| let manifest_dir = env::var("CARGO_MANIFEST_DIR")?; | ||
| let build_dir = PathBuf::from(manifest_dir.as_str()); | ||
| let normalized_build_dir = fs::canonicalize(build_dir)?; | ||
| Ok(normalized_build_dir) | ||
| } | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|  | ||
| use core::ffi::c_void; | ||
| pub static MI_ALIGNMENT_MAX: usize = 1024 * 1024; // 1 MiB | ||
|  | ||
| extern "C" { | ||
| /// Allocate size bytes aligned by alignment. | ||
| /// size: the number of bytes to allocate | ||
| /// alignment: the minimal alignment of the allocated memory. Must be less than MI_ALIGNMENT_MAX | ||
| /// returns: a pointer to the allocated memory, or null if out of memory. The returned pointer is aligned by alignment | ||
| pub fn mi_malloc_aligned(size: usize, alignment: usize) -> *mut c_void; | ||
| pub fn mi_zalloc_aligned(size: usize, alignment: usize) -> *mut c_void; | ||
|  | ||
| /// Free previously allocated memory. | ||
| /// The pointer p must have been allocated before (or be nullptr). | ||
| /// p: the pointer to the memory to free or nullptr | ||
| pub fn mi_free(p: *mut c_void); | ||
| pub fn mi_realloc_aligned(p: *mut c_void, newsize: usize, alignment: usize) -> *mut c_void; | ||
| } | ||
|  | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|  | ||
| #[test] | ||
| fn memory_can_be_allocated_and_freed() { | ||
| let ptr = unsafe { mi_malloc_aligned(8, 8) }.cast::<u8>(); | ||
| assert!(!ptr.cast::<c_void>().is_null()); | ||
| unsafe { mi_free(ptr.cast::<c_void>()) }; | ||
| } | ||
|  | ||
| #[test] | ||
| fn memory_can_be_allocated_zeroed_and_freed() { | ||
| let ptr = unsafe { mi_zalloc_aligned(8, 8) }.cast::<u8>(); | ||
| assert!(!ptr.cast::<c_void>().is_null()); | ||
| unsafe { mi_free(ptr.cast::<c_void>()) }; | ||
| } | ||
|  | ||
| #[test] | ||
| fn memory_can_be_reallocated_and_freed() { | ||
| let ptr = unsafe { mi_malloc_aligned(8, 8) }.cast::<u8>(); | ||
| assert!(!ptr.cast::<c_void>().is_null()); | ||
| let realloc_ptr = unsafe { mi_realloc_aligned(ptr.cast::<c_void>(), 8, 8) }.cast::<u8>(); | ||
| assert!(!realloc_ptr.cast::<c_void>().is_null()); | ||
| unsafe { mi_free(ptr.cast::<c_void>()) }; | ||
| } | ||
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|  | ||
| #[cfg(not(target_family = "wasm"))] | ||
| pub mod mimalloc; | ||
|  | ||
| /// Declare a global allocator if the platform supports it. | ||
| #[macro_export] | ||
| macro_rules! assign_global { | ||
| () => { | ||
| #[cfg(not(target_family = "wasm"))] | ||
| #[global_allocator] | ||
| static GLOBAL: allocator::mimalloc::Mimalloc = allocator::mimalloc::Mimalloc; | ||
| }; | ||
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|  | ||
| use core::alloc::{GlobalAlloc, Layout}; | ||
| use core::ffi::c_void; | ||
|  | ||
| use mimalloc_sys::{mi_free, mi_malloc_aligned, mi_realloc_aligned, mi_zalloc_aligned}; | ||
|  | ||
| pub struct Mimalloc; | ||
|  | ||
| unsafe impl GlobalAlloc for Mimalloc { | ||
| #[inline] | ||
| unsafe fn alloc(&self, layout: Layout) -> *mut u8 { | ||
| debug_assert!(layout.align() < mimalloc_sys::MI_ALIGNMENT_MAX); | ||
| mi_malloc_aligned(layout.size(), layout.align()).cast::<u8>() | ||
| } | ||
|  | ||
| #[inline] | ||
| unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { | ||
| mi_free(ptr.cast::<c_void>()); | ||
| } | ||
|  | ||
| #[inline] | ||
| unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { | ||
| debug_assert!(layout.align() < mimalloc_sys::MI_ALIGNMENT_MAX); | ||
| mi_zalloc_aligned(layout.size(), layout.align()).cast::<u8>() | ||
| } | ||
|  | ||
| #[inline] | ||
| unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { | ||
| debug_assert!(layout.align() < mimalloc_sys::MI_ALIGNMENT_MAX); | ||
| mi_realloc_aligned(ptr.cast::<c_void>(), new_size, layout.align()).cast::<u8>() | ||
| } | ||
| } | ||
|  | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| use std::error::Error; | ||
|  | ||
| #[test] | ||
| fn memory_can_be_allocated_and_freed() -> Result<(), Box<dyn Error>> { | ||
| let layout = Layout::from_size_align(8, 8)?; | ||
| let alloc = Mimalloc; | ||
|  | ||
| unsafe { | ||
| let ptr = alloc.alloc(layout); | ||
| assert!(!ptr.cast::<c_void>().is_null()); | ||
| alloc.dealloc(ptr, layout); | ||
| } | ||
| Ok(()) | ||
| } | ||
|  | ||
| #[test] | ||
| fn memory_can_be_alloc_zeroed_and_freed() -> Result<(), Box<dyn Error>> { | ||
| let layout = Layout::from_size_align(8, 8)?; | ||
| let alloc = Mimalloc; | ||
|  | ||
| unsafe { | ||
| let ptr = alloc.alloc_zeroed(layout); | ||
| assert!(!ptr.cast::<c_void>().is_null()); | ||
| alloc.dealloc(ptr, layout); | ||
| } | ||
| Ok(()) | ||
| } | ||
|  | ||
| #[test] | ||
| fn large_chunks_of_memory_can_be_allocated_and_freed() -> Result<(), Box<dyn Error>> { | ||
| let layout = Layout::from_size_align(2 * 1024 * 1024 * 1024, 8)?; | ||
| let alloc = Mimalloc; | ||
|  | ||
| unsafe { | ||
| let ptr = alloc.alloc(layout); | ||
| assert!(!ptr.cast::<c_void>().is_null()); | ||
| alloc.dealloc(ptr, layout); | ||
| } | ||
| Ok(()) | ||
| } | ||
| } | 
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.