Skip to content

Commit

Permalink
Merge 8e8849c into e2e601d
Browse files Browse the repository at this point in the history
  • Loading branch information
idavis authored Mar 12, 2024
2 parents e2e601d + 8e8849c commit 5c3e644
Show file tree
Hide file tree
Showing 20 changed files with 329 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ __pycache__/
/fuzz/artifacts
/fuzz/coverage
/fuzz/Cargo.lock
.mypy_cache/
.pytest_cache/
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[workspace]
members = [
"allocator",
"allocator/mimalloc-sys",
"compiler/qsc",
"compiler/qsc_ast",
"compiler/qsc_codegen",
Expand Down
15 changes: 15 additions & 0 deletions allocator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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

41 changes: 41 additions & 0 deletions allocator/mimalloc-sys/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 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}
USES_TERMINAL_DOWNLOAD TRUE
USES_TERMINAL_CONFIGURE TRUE
USES_TERMINAL_BUILD TRUE
USES_TERMINAL_INSTALL TRUE
)
20 changes: 20 additions & 0 deletions allocator/mimalloc-sys/Cargo.toml
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"

57 changes: 57 additions & 0 deletions allocator/mimalloc-sys/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 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<dyn Error>> {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=CMakeLists.txt");

compile_mimalloc()?;

Ok(())
}

fn compile_mimalloc() -> Result<(), Box<dyn Error>> {
let build_dir = get_build_dir()?;
let mut config = Config::new(build_dir);

config
.build_target("mimalloc")
.define("CMAKE_BUILD_TYPE", "MinSizeRel")
.define("MI_INSTALL_TOPLEVEL", "ON")
.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-search=static={}",
dst.join("lib").display()
);
println!("cargo:rustc-link-lib=static=mimalloc");

Ok(())
}

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)
}
48 changes: 48 additions & 0 deletions allocator/mimalloc-sys/src/lib.rs
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>()) };
}
}
79 changes: 79 additions & 0 deletions allocator/src/lib.rs
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(())
}
}
1 change: 1 addition & 0 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ def use_python_env(folder):
"-m",
"pip",
"wheel",
"--verbose",
"--wheel-dir",
wheels_dir,
jupyterlab_src,
Expand Down
3 changes: 3 additions & 0 deletions compiler/qsc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
allocator = { path = "../../allocator" }

[dev-dependencies]
criterion = { workspace = true, features = ["cargo_bench_support"] }
expect-test = { workspace = true }
Expand Down
4 changes: 4 additions & 0 deletions compiler/qsc/benches/eval.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#[cfg(not(target_family = "wasm"))]
#[global_allocator]
static GLOBAL: allocator::Mimalloc = allocator::Mimalloc;

use criterion::{criterion_group, criterion_main, Criterion};
use indoc::indoc;
use qsc::{interpret::Interpreter, PackageType};
Expand Down
4 changes: 4 additions & 0 deletions compiler/qsc/benches/large.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#[cfg(not(target_family = "wasm"))]
#[global_allocator]
static GLOBAL: allocator::Mimalloc = allocator::Mimalloc;

use criterion::{criterion_group, criterion_main, Criterion};
use qsc::compile::{self, compile};
use qsc_data_structures::language_features::LanguageFeatures;
Expand Down
4 changes: 4 additions & 0 deletions compiler/qsc/benches/library.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#[cfg(not(target_family = "wasm"))]
#[global_allocator]
static GLOBAL: allocator::Mimalloc = allocator::Mimalloc;

use criterion::{criterion_group, criterion_main, Criterion};
use qsc::compile;
use qsc_frontend::compile::{PackageStore, RuntimeCapabilityFlags};
Expand Down
Loading

0 comments on commit 5c3e644

Please sign in to comment.