Skip to content

Commit d64a1cc

Browse files
authored
chore: use mimalloc for codspeed benchmark allocator (#204)
1 parent 3d32523 commit d64a1cc

3 files changed

Lines changed: 62 additions & 12 deletions

File tree

Cargo.lock

Lines changed: 23 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ rayon = { version = "1.11.0" }
113113
regex = "1.12.2"
114114
vfs = "0.13.0" # for testing with in memory file system
115115

116+
# Benchmark allocator features kept aligned with rspack's `xtask/benchmark`.
117+
[target.'cfg(target_os = "linux")'.dev-dependencies]
118+
mimalloc = { version = "0.1.48", features = ["local_dynamic_tls", "v3"] }
119+
120+
[target.'cfg(target_os = "macos")'.dev-dependencies]
121+
mimalloc = { version = "0.1.48", features = ["v3"] }
122+
123+
[target.'cfg(all(not(target_os = "linux"), not(target_os = "macos"), not(target_family = "wasm")))'.dev-dependencies]
124+
mimalloc = { version = "0.1.48", features = ["v3"] }
125+
116126
[features]
117127
default = ["yarn_pnp"]
118128
## Enables the [PackageJson::raw_json] API,

benches/resolver.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
#[cfg(target_family = "wasm")]
2+
use std::alloc::System;
13
use std::{
2-
alloc::{GlobalAlloc, Layout, System},
4+
alloc::{GlobalAlloc, Layout},
35
env, fs,
46
fs::read_to_string,
57
future::Future,
@@ -9,20 +11,38 @@ use std::{
911
};
1012

1113
#[global_allocator]
12-
static GLOBAL: NeverGrowInPlaceAllocator = NeverGrowInPlaceAllocator;
14+
#[cfg(not(target_family = "wasm"))]
15+
static GLOBAL: NeverGrowInPlaceAllocator<mimalloc::MiMalloc> =
16+
NeverGrowInPlaceAllocator::new(mimalloc::MiMalloc);
1317

14-
/// Delegates `alloc`/`dealloc` to [`System`] but omits [`GlobalAlloc::realloc`],
15-
/// forcing the default "alloc-new + copy + dealloc-old" path so that benchmarks
16-
/// never benefit from non-deterministic in-place growth provided by `libc::realloc`.
17-
struct NeverGrowInPlaceAllocator;
18+
#[global_allocator]
19+
#[cfg(target_family = "wasm")]
20+
static GLOBAL: NeverGrowInPlaceAllocator<System> = NeverGrowInPlaceAllocator::new(System);
21+
22+
/// Delegates `alloc`/`dealloc` to the wrapped allocator but omits
23+
/// [`GlobalAlloc::realloc`], forcing the default "alloc-new + copy + dealloc-old"
24+
/// path so that benchmarks never benefit from non-deterministic in-place growth
25+
/// provided by the underlying allocator's `realloc`. Wrapping `mimalloc::MiMalloc`
26+
/// (instead of using it directly) also keeps `alloc` / `dealloc` visible to
27+
/// CodSpeed's mimalloc white-box allocator tracking.
28+
struct NeverGrowInPlaceAllocator<A> {
29+
allocator: A,
30+
}
31+
32+
impl<A> NeverGrowInPlaceAllocator<A> {
33+
const fn new(allocator: A) -> Self {
34+
Self { allocator }
35+
}
36+
}
1837

19-
unsafe impl GlobalAlloc for NeverGrowInPlaceAllocator {
38+
// SAFETY: Methods simply delegate to the wrapped allocator.
39+
unsafe impl<A: GlobalAlloc> GlobalAlloc for NeverGrowInPlaceAllocator<A> {
2040
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
21-
unsafe { System.alloc(layout) }
41+
self.allocator.alloc(layout)
2242
}
2343

2444
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
25-
unsafe { System.dealloc(ptr, layout) }
45+
self.allocator.dealloc(ptr, layout)
2646
}
2747
}
2848

0 commit comments

Comments
 (0)