From 8b0915631dd82ea508fa9bc3aa2e74e2f06c2d85 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Sat, 9 Mar 2024 16:09:05 -0800 Subject: [PATCH 01/11] Native libraries use mimalloc as global allocator --- .gitignore | 2 ++ Cargo.lock | 22 ++++++++++++++++++++++ Cargo.toml | 1 + compiler/qsc/Cargo.toml | 3 +++ compiler/qsc/benches/eval.rs | 4 ++++ compiler/qsc/benches/large.rs | 4 ++++ compiler/qsc/benches/library.rs | 4 ++++ compiler/qsc/src/bin/qsc.rs | 4 ++++ compiler/qsc/src/bin/qsi.rs | 4 ++++ fuzz/Cargo.toml | 3 +++ fuzz/fuzz_targets/compile.rs | 4 ++++ pip/Cargo.toml | 3 +++ pip/src/lib.rs | 4 ++++ 13 files changed, 62 insertions(+) diff --git a/.gitignore b/.gitignore index 1b35b03118..8cbb2b6615 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ __pycache__/ /fuzz/artifacts /fuzz/coverage /fuzz/Cargo.lock +.mypy_cache/ +.pytest_cache/ diff --git a/Cargo.lock b/Cargo.lock index 829b025fe2..dcce91fc84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -435,6 +435,7 @@ name = "fuzz" version = "0.0.0" dependencies = [ "libfuzzer-sys", + "mimalloc", "qsc", ] @@ -577,6 +578,16 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libmimalloc-sys" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "library" version = "0.0.0" @@ -660,6 +671,15 @@ dependencies = [ "syn", ] +[[package]] +name = "mimalloc" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" +dependencies = [ + "libmimalloc-sys", +] + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -898,6 +918,7 @@ dependencies = [ "indoc", "log", "miette", + "mimalloc", "num-bigint", "num-complex", "qsc_ast", @@ -1097,6 +1118,7 @@ name = "qsharp" version = "0.0.0" dependencies = [ "miette", + "mimalloc", "num-bigint", "num-complex", "pyo3", diff --git a/Cargo.toml b/Cargo.toml index 1c51a58ac8..4e1ed2f0a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ libfuzzer-sys = "0.4" log = "0.4" miette = "5.10" thiserror = "1.0" +mimalloc = { version = "0.1.39", default-features = false } num-bigint = "0.4" num-complex = "0.4" num-traits = "0.2" diff --git a/compiler/qsc/Cargo.toml b/compiler/qsc/Cargo.toml index 35d09eb087..2d208b03dc 100644 --- a/compiler/qsc/Cargo.toml +++ b/compiler/qsc/Cargo.toml @@ -29,6 +29,9 @@ qsc_project = { path = "../qsc_project", features = ["fs"] } rustc-hash = { workspace = true } thiserror = { workspace = true } +[target.'cfg(not(any(target_family = "wasm")))'.dependencies] +mimalloc = { workspace = true } + [dev-dependencies] criterion = { workspace = true, features = ["cargo_bench_support"] } expect-test = { workspace = true } diff --git a/compiler/qsc/benches/eval.rs b/compiler/qsc/benches/eval.rs index b2698de3b2..ca3f42c75a 100644 --- a/compiler/qsc/benches/eval.rs +++ b/compiler/qsc/benches/eval.rs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#[cfg(not(target_family = "wasm"))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + use criterion::{criterion_group, criterion_main, Criterion}; use indoc::indoc; use qsc::{interpret::Interpreter, PackageType}; diff --git a/compiler/qsc/benches/large.rs b/compiler/qsc/benches/large.rs index 1d3ca57eb5..e454307ea2 100644 --- a/compiler/qsc/benches/large.rs +++ b/compiler/qsc/benches/large.rs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#[cfg(not(target_family = "wasm"))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + use criterion::{criterion_group, criterion_main, Criterion}; use qsc::compile::{self, compile}; use qsc_data_structures::language_features::LanguageFeatures; diff --git a/compiler/qsc/benches/library.rs b/compiler/qsc/benches/library.rs index c60ceeb6fc..5d8bcacaeb 100644 --- a/compiler/qsc/benches/library.rs +++ b/compiler/qsc/benches/library.rs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#[cfg(not(target_family = "wasm"))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + use criterion::{criterion_group, criterion_main, Criterion}; use qsc::compile; use qsc_frontend::compile::{PackageStore, RuntimeCapabilityFlags}; diff --git a/compiler/qsc/src/bin/qsc.rs b/compiler/qsc/src/bin/qsc.rs index 9b47d8f039..3ebd68a614 100644 --- a/compiler/qsc/src/bin/qsc.rs +++ b/compiler/qsc/src/bin/qsc.rs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#[cfg(not(target_family = "wasm"))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + use clap::{crate_version, ArgGroup, Parser, ValueEnum}; use log::info; use miette::{Context, IntoDiagnostic, Report}; diff --git a/compiler/qsc/src/bin/qsi.rs b/compiler/qsc/src/bin/qsi.rs index 5e6d2dbfef..f6df5e61dd 100644 --- a/compiler/qsc/src/bin/qsi.rs +++ b/compiler/qsc/src/bin/qsi.rs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#[cfg(not(target_family = "wasm"))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + use clap::{crate_version, Parser}; use miette::{Context, IntoDiagnostic, Report, Result}; use num_bigint::BigUint; diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 16dc9292a7..3936633180 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -16,6 +16,9 @@ cargo-fuzz = true libfuzzer-sys = { workspace = true, optional = true } qsc = { path = "../compiler/qsc" } +[target.'cfg(not(any(target_family = "wasm")))'.dependencies] +mimalloc = { workspace = true } + [features] do_fuzz = [ "dep:libfuzzer-sys" ] diff --git a/fuzz/fuzz_targets/compile.rs b/fuzz/fuzz_targets/compile.rs index 05c5ee7f55..c1842a83ac 100644 --- a/fuzz/fuzz_targets/compile.rs +++ b/fuzz/fuzz_targets/compile.rs @@ -3,6 +3,10 @@ #![no_main] +#[cfg(not(target_family = "wasm"))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + #[cfg(feature = "do_fuzz")] use libfuzzer_sys::fuzz_target; use qsc::{hir::PackageId, target::Profile, LanguageFeatures, PackageStore, SourceMap}; diff --git a/pip/Cargo.toml b/pip/Cargo.toml index 369a679b62..11e1bb08ba 100644 --- a/pip/Cargo.toml +++ b/pip/Cargo.toml @@ -20,6 +20,9 @@ rustc-hash = { workspace = true } [lints] workspace = true +[target.'cfg(not(any(target_family = "wasm")))'.dependencies] +mimalloc = { workspace = true } + [target.'cfg(not(any(target_os = "windows")))'.dependencies] pyo3 = { workspace = true, features = ["abi3-py37", "extension-module", "num-bigint"] } diff --git a/pip/src/lib.rs b/pip/src/lib.rs index f126254403..d9114c03d2 100644 --- a/pip/src/lib.rs +++ b/pip/src/lib.rs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +#[cfg(not(target_family = "wasm"))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + mod displayable_output; mod fs; mod interpreter; From 9d669d6927898a02787b8f49058699980991dafa Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 10:48:51 -0700 Subject: [PATCH 02/11] Implementing mimalloc-sys crate and dynamic mimalloc compilation --- Cargo.lock | 41 ++++++++------ Cargo.toml | 3 +- allocator/Cargo.toml | 15 +++++ allocator/mimalloc-sys/CMakeLists.txt | 42 ++++++++++++++ allocator/mimalloc-sys/Cargo.toml | 20 +++++++ allocator/mimalloc-sys/build.rs | 49 +++++++++++++++++ allocator/mimalloc-sys/src/lib.rs | 48 ++++++++++++++++ allocator/src/lib.rs | 79 +++++++++++++++++++++++++++ compiler/qsc/Cargo.toml | 2 +- compiler/qsc/benches/eval.rs | 2 +- compiler/qsc/benches/large.rs | 2 +- compiler/qsc/benches/library.rs | 2 +- compiler/qsc/src/bin/qsc.rs | 2 +- compiler/qsc/src/bin/qsi.rs | 2 +- fuzz/Cargo.toml | 2 +- fuzz/fuzz_targets/compile.rs | 2 +- pip/Cargo.toml | 2 +- pip/src/lib.rs | 2 +- 18 files changed, 288 insertions(+), 29 deletions(-) create mode 100644 allocator/Cargo.toml create mode 100644 allocator/mimalloc-sys/CMakeLists.txt create mode 100644 allocator/mimalloc-sys/Cargo.toml create mode 100644 allocator/mimalloc-sys/build.rs create mode 100644 allocator/mimalloc-sys/src/lib.rs create mode 100644 allocator/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index dcce91fc84..e1d142a86a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,13 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator" +version = "0.0.0" +dependencies = [ + "mimalloc-sys", +] + [[package]] name = "anes" version = "0.1.6" @@ -234,6 +241,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "cmake" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.0" @@ -434,8 +450,8 @@ dependencies = [ name = "fuzz" version = "0.0.0" dependencies = [ + "allocator", "libfuzzer-sys", - "mimalloc", "qsc", ] @@ -578,16 +594,6 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "libmimalloc-sys" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "library" version = "0.0.0" @@ -672,12 +678,11 @@ dependencies = [ ] [[package]] -name = "mimalloc" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" +name = "mimalloc-sys" +version = "0.0.0" dependencies = [ - "libmimalloc-sys", + "cc", + "cmake", ] [[package]] @@ -911,6 +916,7 @@ dependencies = [ name = "qsc" version = "0.0.0" dependencies = [ + "allocator", "clap", "criterion", "env_logger", @@ -918,7 +924,6 @@ dependencies = [ "indoc", "log", "miette", - "mimalloc", "num-bigint", "num-complex", "qsc_ast", @@ -1117,8 +1122,8 @@ dependencies = [ name = "qsharp" version = "0.0.0" dependencies = [ + "allocator", "miette", - "mimalloc", "num-bigint", "num-complex", "pyo3", diff --git a/Cargo.toml b/Cargo.toml index 4e1ed2f0a8..5e96d1009d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,7 @@ [workspace] members = [ + "allocator", + "allocator/mimalloc-sys", "compiler/qsc", "compiler/qsc_ast", "compiler/qsc_codegen", @@ -47,7 +49,6 @@ libfuzzer-sys = "0.4" log = "0.4" miette = "5.10" thiserror = "1.0" -mimalloc = { version = "0.1.39", default-features = false } num-bigint = "0.4" num-complex = "0.4" num-traits = "0.2" diff --git a/allocator/Cargo.toml b/allocator/Cargo.toml new file mode 100644 index 0000000000..e75459172f --- /dev/null +++ b/allocator/Cargo.toml @@ -0,0 +1,15 @@ +[package] +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 + diff --git a/allocator/mimalloc-sys/CMakeLists.txt b/allocator/mimalloc-sys/CMakeLists.txt new file mode 100644 index 0000000000..bbfa8aa8a5 --- /dev/null +++ b/allocator/mimalloc-sys/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +cmake_minimum_required(VERSION 3.10.0) + +# Copy the command line arguments to a cache variable so that they can be used +# with the inner project. This is needed because the inner project +# needs to use the same configuration and the command line arguments are not +# passed to the inner project. +# This also manifests itself in apple silicon systems where the inner project +# defaults to x86_64 even if the outer project is arm64. +# This needs to be done before the project command is called. +if (NOT ALLOCATOR_CMAKE_CL_ARGS) + # get all cache variables + get_cmake_property(vars CACHE_VARIABLES) + foreach(var ${vars}) + get_property(currentHelpString CACHE "${var}" PROPERTY HELPSTRING) + # only add the cache variable to the list if it is set on the command line + if("${currentHelpString}" MATCHES "No help, variable specified on the command line." OR "${currentHelpString}" STREQUAL "") + message ("${var} = [${${var}}] -- ${currentHelpString}") + list(APPEND ALLOCATOR_CMAKE_CL_ARGS "-D${var}=${${var}}") + endif() + endforeach() + # cache the command line arguments + set(ALLOCATOR_CMAKE_CL_ARGS ${ALLOCATOR_CMAKE_CL_ARGS} CACHE STRING "comment") +endif () + +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 + CMAKE_ARGS ${ALLOCATOR_CMAKE_CL_ARGS} + BUILD_COMMAND ninja + USES_TERMINAL_DOWNLOAD TRUE + USES_TERMINAL_CONFIGURE TRUE + USES_TERMINAL_BUILD TRUE + USES_TERMINAL_INSTALL TRUE +) diff --git a/allocator/mimalloc-sys/Cargo.toml b/allocator/mimalloc-sys/Cargo.toml new file mode 100644 index 0000000000..cbf2546887 --- /dev/null +++ b/allocator/mimalloc-sys/Cargo.toml @@ -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" + diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs new file mode 100644 index 0000000000..d976efaa2a --- /dev/null +++ b/allocator/mimalloc-sys/build.rs @@ -0,0 +1,49 @@ +// 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::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> { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=CMakeLists.txt"); + + compile_mimalloc()?; + + Ok(()) +} + +fn compile_mimalloc() -> Result<(), Box> { + let build_dir = get_build_dir()?; + let mut config = Config::new(build_dir); + + config + .generator("Ninja") + .define("CMAKE_BUILD_TYPE", "MinSizeRel") + .define("MI_INSTALL_TOPLEVEL", "ON") + .build_target("mimalloc-prefix/src/mimalloc-stamp/mimalloc-install") + .env("ALLOCATOR_MIMALLOC_TAG", ALLOCATOR_MIMALLOC_TAG); + + let dst = config.build(); + println!("cargo:rustc-link-search=native={}/lib", dst.display()); + println!("cargo:rustc-link-lib=static=mimalloc"); + + Ok(()) +} + +fn get_build_dir() -> Result> { + 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) +} diff --git a/allocator/mimalloc-sys/src/lib.rs b/allocator/mimalloc-sys/src/lib.rs new file mode 100644 index 0000000000..528ba7ef2e --- /dev/null +++ b/allocator/mimalloc-sys/src/lib.rs @@ -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::(); + assert!(!ptr.cast::().is_null()); + unsafe { mi_free(ptr.cast::()) }; + } + + #[test] + fn memory_can_be_allocated_zeroed_and_freed() { + let ptr = unsafe { mi_zalloc_aligned(8, 8) }.cast::(); + assert!(!ptr.cast::().is_null()); + unsafe { mi_free(ptr.cast::()) }; + } + + #[test] + fn memory_can_be_reallocated_and_freed() { + let ptr = unsafe { mi_malloc_aligned(8, 8) }.cast::(); + assert!(!ptr.cast::().is_null()); + let realloc_ptr = unsafe { mi_realloc_aligned(ptr.cast::(), 8, 8) }.cast::(); + assert!(!realloc_ptr.cast::().is_null()); + unsafe { mi_free(ptr.cast::()) }; + } +} diff --git a/allocator/src/lib.rs b/allocator/src/lib.rs new file mode 100644 index 0000000000..f76418cb9e --- /dev/null +++ b/allocator/src/lib.rs @@ -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::() + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + mi_free(ptr.cast::()); + } + + #[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::() + } + + #[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::(), new_size, layout.align()).cast::() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::error::Error; + + #[test] + fn memory_can_be_allocated_and_freed() -> Result<(), Box> { + let layout = Layout::from_size_align(8, 8)?; + let alloc = Mimalloc; + + unsafe { + let ptr = alloc.alloc(layout); + assert!(!ptr.cast::().is_null()); + alloc.dealloc(ptr, layout); + } + Ok(()) + } + + #[test] + fn memory_can_be_alloc_zeroed_and_freed() -> Result<(), Box> { + let layout = Layout::from_size_align(8, 8)?; + let alloc = Mimalloc; + + unsafe { + let ptr = alloc.alloc_zeroed(layout); + assert!(!ptr.cast::().is_null()); + alloc.dealloc(ptr, layout); + } + Ok(()) + } + + #[test] + fn large_chunks_of_memory_can_be_allocated_and_freed() -> Result<(), Box> { + let layout = Layout::from_size_align(2 * 1024 * 1024 * 1024, 8)?; + let alloc = Mimalloc; + + unsafe { + let ptr = alloc.alloc(layout); + assert!(!ptr.cast::().is_null()); + alloc.dealloc(ptr, layout); + } + Ok(()) + } +} diff --git a/compiler/qsc/Cargo.toml b/compiler/qsc/Cargo.toml index 2d208b03dc..37698069f5 100644 --- a/compiler/qsc/Cargo.toml +++ b/compiler/qsc/Cargo.toml @@ -30,7 +30,7 @@ rustc-hash = { workspace = true } thiserror = { workspace = true } [target.'cfg(not(any(target_family = "wasm")))'.dependencies] -mimalloc = { workspace = true } +allocator = { path = "../../allocator" } [dev-dependencies] criterion = { workspace = true, features = ["cargo_bench_support"] } diff --git a/compiler/qsc/benches/eval.rs b/compiler/qsc/benches/eval.rs index ca3f42c75a..558f1b5059 100644 --- a/compiler/qsc/benches/eval.rs +++ b/compiler/qsc/benches/eval.rs @@ -3,7 +3,7 @@ #[cfg(not(target_family = "wasm"))] #[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +static GLOBAL: allocator::Mimalloc = allocator::Mimalloc; use criterion::{criterion_group, criterion_main, Criterion}; use indoc::indoc; diff --git a/compiler/qsc/benches/large.rs b/compiler/qsc/benches/large.rs index e454307ea2..75ceb0679f 100644 --- a/compiler/qsc/benches/large.rs +++ b/compiler/qsc/benches/large.rs @@ -3,7 +3,7 @@ #[cfg(not(target_family = "wasm"))] #[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +static GLOBAL: allocator::Mimalloc = allocator::Mimalloc; use criterion::{criterion_group, criterion_main, Criterion}; use qsc::compile::{self, compile}; diff --git a/compiler/qsc/benches/library.rs b/compiler/qsc/benches/library.rs index 5d8bcacaeb..8af3d5e6dd 100644 --- a/compiler/qsc/benches/library.rs +++ b/compiler/qsc/benches/library.rs @@ -3,7 +3,7 @@ #[cfg(not(target_family = "wasm"))] #[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +static GLOBAL: allocator::Mimalloc = allocator::Mimalloc; use criterion::{criterion_group, criterion_main, Criterion}; use qsc::compile; diff --git a/compiler/qsc/src/bin/qsc.rs b/compiler/qsc/src/bin/qsc.rs index 3ebd68a614..4507b6d112 100644 --- a/compiler/qsc/src/bin/qsc.rs +++ b/compiler/qsc/src/bin/qsc.rs @@ -3,7 +3,7 @@ #[cfg(not(target_family = "wasm"))] #[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +static GLOBAL: allocator::Mimalloc = allocator::Mimalloc; use clap::{crate_version, ArgGroup, Parser, ValueEnum}; use log::info; diff --git a/compiler/qsc/src/bin/qsi.rs b/compiler/qsc/src/bin/qsi.rs index f6df5e61dd..2a4c61f729 100644 --- a/compiler/qsc/src/bin/qsi.rs +++ b/compiler/qsc/src/bin/qsi.rs @@ -3,7 +3,7 @@ #[cfg(not(target_family = "wasm"))] #[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +static GLOBAL: allocator::Mimalloc = allocator::Mimalloc; use clap::{crate_version, Parser}; use miette::{Context, IntoDiagnostic, Report, Result}; diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 3936633180..34b9ba6609 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -17,7 +17,7 @@ libfuzzer-sys = { workspace = true, optional = true } qsc = { path = "../compiler/qsc" } [target.'cfg(not(any(target_family = "wasm")))'.dependencies] -mimalloc = { workspace = true } +allocator = { path = "../allocator" } [features] do_fuzz = [ "dep:libfuzzer-sys" ] diff --git a/fuzz/fuzz_targets/compile.rs b/fuzz/fuzz_targets/compile.rs index c1842a83ac..6e5d06a6ae 100644 --- a/fuzz/fuzz_targets/compile.rs +++ b/fuzz/fuzz_targets/compile.rs @@ -5,7 +5,7 @@ #[cfg(not(target_family = "wasm"))] #[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +static GLOBAL: allocator::Mimalloc = allocator::Mimalloc; #[cfg(feature = "do_fuzz")] use libfuzzer_sys::fuzz_target; diff --git a/pip/Cargo.toml b/pip/Cargo.toml index 11e1bb08ba..fe4467e44d 100644 --- a/pip/Cargo.toml +++ b/pip/Cargo.toml @@ -21,7 +21,7 @@ rustc-hash = { workspace = true } workspace = true [target.'cfg(not(any(target_family = "wasm")))'.dependencies] -mimalloc = { workspace = true } +allocator = { path = "../allocator" } [target.'cfg(not(any(target_os = "windows")))'.dependencies] pyo3 = { workspace = true, features = ["abi3-py37", "extension-module", "num-bigint"] } diff --git a/pip/src/lib.rs b/pip/src/lib.rs index d9114c03d2..1ba3fb619e 100644 --- a/pip/src/lib.rs +++ b/pip/src/lib.rs @@ -3,7 +3,7 @@ #[cfg(not(target_family = "wasm"))] #[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; +static GLOBAL: allocator::Mimalloc = allocator::Mimalloc; mod displayable_output; mod fs; From 8aba7d21fb83e1ebab37b54fb9173e3f945b8449 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 11:10:36 -0700 Subject: [PATCH 03/11] Remove ninja dep --- allocator/mimalloc-sys/CMakeLists.txt | 1 - allocator/mimalloc-sys/build.rs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/allocator/mimalloc-sys/CMakeLists.txt b/allocator/mimalloc-sys/CMakeLists.txt index bbfa8aa8a5..2088ee1161 100644 --- a/allocator/mimalloc-sys/CMakeLists.txt +++ b/allocator/mimalloc-sys/CMakeLists.txt @@ -34,7 +34,6 @@ ExternalProject_Add(mimalloc GIT_SHALLOW TRUE GIT_PROGRESS TRUE CMAKE_ARGS ${ALLOCATOR_CMAKE_CL_ARGS} - BUILD_COMMAND ninja USES_TERMINAL_DOWNLOAD TRUE USES_TERMINAL_CONFIGURE TRUE USES_TERMINAL_BUILD TRUE diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs index d976efaa2a..a6dc0d5e34 100644 --- a/allocator/mimalloc-sys/build.rs +++ b/allocator/mimalloc-sys/build.rs @@ -28,10 +28,9 @@ fn compile_mimalloc() -> Result<(), Box> { let mut config = Config::new(build_dir); config - .generator("Ninja") .define("CMAKE_BUILD_TYPE", "MinSizeRel") .define("MI_INSTALL_TOPLEVEL", "ON") - .build_target("mimalloc-prefix/src/mimalloc-stamp/mimalloc-install") + .build_target("mimalloc") .env("ALLOCATOR_MIMALLOC_TAG", ALLOCATOR_MIMALLOC_TAG); let dst = config.build(); From 10933e4d3cb96bc5259b5467d4f907bee4423275 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 11:34:12 -0700 Subject: [PATCH 04/11] Static linking crt --- allocator/mimalloc-sys/build.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs index a6dc0d5e34..b7b37778c5 100644 --- a/allocator/mimalloc-sys/build.rs +++ b/allocator/mimalloc-sys/build.rs @@ -28,10 +28,12 @@ fn compile_mimalloc() -> Result<(), Box> { let mut config = Config::new(build_dir); config + .build_target("mimalloc") .define("CMAKE_BUILD_TYPE", "MinSizeRel") .define("MI_INSTALL_TOPLEVEL", "ON") - .build_target("mimalloc") - .env("ALLOCATOR_MIMALLOC_TAG", ALLOCATOR_MIMALLOC_TAG); + .env("ALLOCATOR_MIMALLOC_TAG", ALLOCATOR_MIMALLOC_TAG) + .static_crt(true) + .very_verbose(true); let dst = config.build(); println!("cargo:rustc-link-search=native={}/lib", dst.display()); From 9618cda7f461509883564d0c52063c88031bf9f1 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 12:10:59 -0700 Subject: [PATCH 05/11] Adding some verbosity and clean path --- allocator/mimalloc-sys/build.rs | 9 ++++++++- build.py | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs index b7b37778c5..84029a4934 100644 --- a/allocator/mimalloc-sys/build.rs +++ b/allocator/mimalloc-sys/build.rs @@ -36,7 +36,14 @@ fn compile_mimalloc() -> Result<(), Box> { .very_verbose(true); let dst = config.build(); - println!("cargo:rustc-link-search=native={}/lib", dst.display()); + println!( + "cargo:rustc-link-search=native={}", + dst.join("lib").display() + ); + println!( + "cargo:rustc-link-search=static={}", + dst.join("lib").display() + ); println!("cargo:rustc-link-lib=static=mimalloc"); Ok(()) diff --git a/build.py b/build.py index 25c8d25b88..5d974ffac9 100755 --- a/build.py +++ b/build.py @@ -403,6 +403,7 @@ def use_python_env(folder): "-m", "pip", "wheel", + "--verbose", "--wheel-dir", wheels_dir, jupyterlab_src, From b0d95425696f3e0a45c9a2f5b4d38a7262a33d2e Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 12:29:34 -0700 Subject: [PATCH 06/11] Seeing if windows crash is due to 2.x --- allocator/mimalloc-sys/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs index 84029a4934..1a32a6ec46 100644 --- a/allocator/mimalloc-sys/build.rs +++ b/allocator/mimalloc-sys/build.rs @@ -10,9 +10,9 @@ use std::path::PathBuf; use cmake::Config; // 1.8.2 -//static ALLOCATOR_MIMALLOC_TAG: &str = "b66e3214d8a104669c2ec05ae91ebc26a8f5ab78"; +static ALLOCATOR_MIMALLOC_TAG: &str = "b66e3214d8a104669c2ec05ae91ebc26a8f5ab78"; // 2.1.2 -static ALLOCATOR_MIMALLOC_TAG: &str = "43ce4bd7fd34bcc730c1c7471c99995597415488"; +//static ALLOCATOR_MIMALLOC_TAG: &str = "43ce4bd7fd34bcc730c1c7471c99995597415488"; fn main() -> Result<(), Box> { println!("cargo:rerun-if-changed=build.rs"); From 86facfed0689d325c21bc0de005e0327597537cc Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 13:12:15 -0700 Subject: [PATCH 07/11] Trying more windows flags. --- allocator/mimalloc-sys/build.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs index 1a32a6ec46..ee160b9259 100644 --- a/allocator/mimalloc-sys/build.rs +++ b/allocator/mimalloc-sys/build.rs @@ -10,9 +10,9 @@ use std::path::PathBuf; use cmake::Config; // 1.8.2 -static ALLOCATOR_MIMALLOC_TAG: &str = "b66e3214d8a104669c2ec05ae91ebc26a8f5ab78"; +//static ALLOCATOR_MIMALLOC_TAG: &str = "b66e3214d8a104669c2ec05ae91ebc26a8f5ab78"; // 2.1.2 -//static ALLOCATOR_MIMALLOC_TAG: &str = "43ce4bd7fd34bcc730c1c7471c99995597415488"; +static ALLOCATOR_MIMALLOC_TAG: &str = "43ce4bd7fd34bcc730c1c7471c99995597415488"; fn main() -> Result<(), Box> { println!("cargo:rerun-if-changed=build.rs"); @@ -28,9 +28,12 @@ fn compile_mimalloc() -> Result<(), Box> { let mut config = Config::new(build_dir); config - .build_target("mimalloc") + //.build_target("mimalloc") + .no_build_target(true) .define("CMAKE_BUILD_TYPE", "MinSizeRel") .define("MI_INSTALL_TOPLEVEL", "ON") + .define("MI_OVERRIDE", "OFF") + .define("MI_WIN_REDIRECT", "OFF") .env("ALLOCATOR_MIMALLOC_TAG", ALLOCATOR_MIMALLOC_TAG) .static_crt(true) .very_verbose(true); @@ -40,10 +43,6 @@ fn compile_mimalloc() -> Result<(), Box> { "cargo:rustc-link-search=native={}", dst.join("lib").display() ); - println!( - "cargo:rustc-link-search=static={}", - dst.join("lib").display() - ); println!("cargo:rustc-link-lib=static=mimalloc"); Ok(()) From 21e1eb54efcd781d74d251fb18ac2253f2f92786 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 15:43:15 -0700 Subject: [PATCH 08/11] Simplifying compilation. --- allocator/mimalloc-sys/CMakeLists.txt | 26 ++----------- allocator/mimalloc-sys/build.rs | 54 +++++++++++++++++++-------- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/allocator/mimalloc-sys/CMakeLists.txt b/allocator/mimalloc-sys/CMakeLists.txt index 2088ee1161..7004d3905c 100644 --- a/allocator/mimalloc-sys/CMakeLists.txt +++ b/allocator/mimalloc-sys/CMakeLists.txt @@ -3,27 +3,6 @@ cmake_minimum_required(VERSION 3.10.0) -# Copy the command line arguments to a cache variable so that they can be used -# with the inner project. This is needed because the inner project -# needs to use the same configuration and the command line arguments are not -# passed to the inner project. -# This also manifests itself in apple silicon systems where the inner project -# defaults to x86_64 even if the outer project is arm64. -# This needs to be done before the project command is called. -if (NOT ALLOCATOR_CMAKE_CL_ARGS) - # get all cache variables - get_cmake_property(vars CACHE_VARIABLES) - foreach(var ${vars}) - get_property(currentHelpString CACHE "${var}" PROPERTY HELPSTRING) - # only add the cache variable to the list if it is set on the command line - if("${currentHelpString}" MATCHES "No help, variable specified on the command line." OR "${currentHelpString}" STREQUAL "") - message ("${var} = [${${var}}] -- ${currentHelpString}") - list(APPEND ALLOCATOR_CMAKE_CL_ARGS "-D${var}=${${var}}") - endif() - endforeach() - # cache the command line arguments - set(ALLOCATOR_CMAKE_CL_ARGS ${ALLOCATOR_CMAKE_CL_ARGS} CACHE STRING "comment") -endif () project(allocator_external) include(ExternalProject) @@ -33,7 +12,10 @@ ExternalProject_Add(mimalloc GIT_TAG $ENV{ALLOCATOR_MIMALLOC_TAG} GIT_SHALLOW TRUE GIT_PROGRESS TRUE - CMAKE_ARGS ${ALLOCATOR_CMAKE_CL_ARGS} + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" USES_TERMINAL_DOWNLOAD TRUE USES_TERMINAL_CONFIGURE TRUE USES_TERMINAL_BUILD TRUE diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs index ee160b9259..ab5433f4a3 100644 --- a/allocator/mimalloc-sys/build.rs +++ b/allocator/mimalloc-sys/build.rs @@ -5,7 +5,7 @@ use std::boxed::Box; use std::env; use std::error::Error; use std::fs; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use cmake::Config; @@ -15,37 +15,59 @@ use cmake::Config; static ALLOCATOR_MIMALLOC_TAG: &str = "43ce4bd7fd34bcc730c1c7471c99995597415488"; fn main() -> Result<(), Box> { + let dst = download_mimalloc()?; + compile_mimalloc(&dst); println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=CMakeLists.txt"); + Ok(()) +} - compile_mimalloc()?; +// 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"); - Ok(()) + 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.compile("mimalloc"); + + println!( + "cargo:rustc-link-search=native={}", + dst.join("lib").display() + ); + println!("cargo:rustc-link-lib=static=mimalloc"); } -fn compile_mimalloc() -> Result<(), Box> { +// Use cmake to download mimallloc source code and stage +// it in the build directory. +fn download_mimalloc() -> Result> { let build_dir = get_build_dir()?; let mut config = Config::new(build_dir); config - //.build_target("mimalloc") .no_build_target(true) - .define("CMAKE_BUILD_TYPE", "MinSizeRel") - .define("MI_INSTALL_TOPLEVEL", "ON") - .define("MI_OVERRIDE", "OFF") - .define("MI_WIN_REDIRECT", "OFF") .env("ALLOCATOR_MIMALLOC_TAG", ALLOCATOR_MIMALLOC_TAG) - .static_crt(true) .very_verbose(true); let dst = config.build(); - println!( - "cargo:rustc-link-search=native={}", - dst.join("lib").display() - ); - println!("cargo:rustc-link-lib=static=mimalloc"); - Ok(()) + Ok(dst) } fn get_build_dir() -> Result> { From db58fff2943f8e10b8195e45fb7dc562b84223dd Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Tue, 12 Mar 2024 16:46:11 -0700 Subject: [PATCH 09/11] Optimizing perf and setting up windows crt --- allocator/mimalloc-sys/build.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/allocator/mimalloc-sys/build.rs b/allocator/mimalloc-sys/build.rs index ab5433f4a3..955fdb2683 100644 --- a/allocator/mimalloc-sys/build.rs +++ b/allocator/mimalloc-sys/build.rs @@ -43,7 +43,13 @@ fn compile_mimalloc(dst: &Path) { 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"); From a8a4dcdd8c0b94f40d9990c7d860e54354402604 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Wed, 13 Mar 2024 10:37:47 -0700 Subject: [PATCH 10/11] Updating building instructions --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 113ce041c6..341f27a229 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,13 @@ Code from this repository powers the Q# development experience on ) - Rust () - Node.js () - wasm-pack () +- cmake () and a C compiler The build script will check these dependencies and their versions and fail if not met. (Or run `python ./prereqs.py` directly to check if the minimum required versions are installed). From 3f46b509fbaf75641073cd0837b97dff742f4dc8 Mon Sep 17 00:00:00 2001 From: Ian Davis Date: Wed, 13 Mar 2024 15:35:15 -0700 Subject: [PATCH 11/11] Cleaning up --- allocator/mimalloc-sys/CMakeLists.txt | 3 --- build.py | 1 - 2 files changed, 4 deletions(-) diff --git a/allocator/mimalloc-sys/CMakeLists.txt b/allocator/mimalloc-sys/CMakeLists.txt index 7004d3905c..0d745774a4 100644 --- a/allocator/mimalloc-sys/CMakeLists.txt +++ b/allocator/mimalloc-sys/CMakeLists.txt @@ -17,7 +17,4 @@ ExternalProject_Add(mimalloc INSTALL_COMMAND "" TEST_COMMAND "" USES_TERMINAL_DOWNLOAD TRUE - USES_TERMINAL_CONFIGURE TRUE - USES_TERMINAL_BUILD TRUE - USES_TERMINAL_INSTALL TRUE ) diff --git a/build.py b/build.py index 5d974ffac9..25c8d25b88 100755 --- a/build.py +++ b/build.py @@ -403,7 +403,6 @@ def use_python_env(folder): "-m", "pip", "wheel", - "--verbose", "--wheel-dir", wheels_dir, jupyterlab_src,