-
Notifications
You must be signed in to change notification settings - Fork 124
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.