Skip to content

perf(alloc): skip `*_aligned calls when alignment fits default - #170

Open
chirizxc wants to merge 1 commit into
purpleprotocol:masterfrom
chirizxc:fast-path
Open

perf(alloc): skip `*_aligned calls when alignment fits default#170
chirizxc wants to merge 1 commit into
purpleprotocol:masterfrom
chirizxc:fast-path

Conversation

@chirizxc

@chirizxc chirizxc commented Aug 7, 2026

Copy link
Copy Markdown

For my library, this provides a small speedup (about ~3.2%):

py benchmark/b.py
file: example.toml
size: 3.93 KiB
runs: 1,000 x 5

allocator                 time    vs default        memory        wall
--------------------------------------------------------------------------
default               0.0514s        1.00x      15.39 MB     0.384s
mimalloc              0.0438s        1.17x      15.68 MB     0.331s
fp-mimalloc           0.0408s        1.26x      15.76 MB     0.306spy benchmark/b.py
file: example.toml
size: 3.93 KiB
runs: 1,000 x 5

allocator                 time    vs default        memory        wall
--------------------------------------------------------------------------
default               0.0493s        1.00x      15.25 MB     0.360s
mimalloc              0.0437s        1.13x      15.75 MB     0.321s
fp-mimalloc           0.0415s        1.19x      15.58 MB     0.316spy benchmark/b.py
file: example.toml
size: 3.93 KiB
runs: 1,000 x 5

allocator                 time    vs default        memory        wall
--------------------------------------------------------------------------
default               0.0530s        1.00x      15.20 MB     0.371s
mimalloc              0.0436s        1.22x      15.50 MB     0.322s
fp-mimalloc           0.0440s        1.21x      15.69 MB     0.321spy benchmark/b.py
file: example.toml
size: 3.93 KiB
runs: 1,000 x 5

allocator                 time    vs default        memory        wall
--------------------------------------------------------------------------
default               0.0541s        1.00x      15.33 MB     0.376s
mimalloc              0.0415s        1.30x      15.62 MB     0.306s
fp-mimalloc           0.0409s        1.32x      15.52 MB     0.317spy benchmark/b.py
file: example.toml
size: 3.93 KiB
runs: 1,000 x 5

allocator                 time    vs default        memory        wall
--------------------------------------------------------------------------
default               0.0494s        1.00x      15.17 MB     0.356s
mimalloc              0.0425s        1.16x      15.70 MB     0.323s
fp-mimalloc           0.0412s        1.20x      15.83 MB     0.322spy benchmark/b.py
file: example.toml
size: 3.93 KiB
runs: 1,000 x 5

allocator                 time    vs default        memory        wall
--------------------------------------------------------------------------
default               0.0540s        1.00x      15.18 MB     0.386s
mimalloc              0.0430s        1.26x      15.52 MB     0.321s
fp-mimalloc           0.0414s        1.30x      15.81 MB     0.313spy benchmark/b.py
file: example.toml
size: 3.93 KiB
runs: 1,000 x 5

allocator                 time    vs default        memory        wall
--------------------------------------------------------------------------
default               0.0512s        1.00x      15.14 MB     0.364s
mimalloc              0.0464s        1.10x      15.59 MB     0.335s
fp-mimalloc           0.0446s        1.15x      15.55 MB     0.321s

Comment thread src/lib.rs
Comment on lines +86 to +96
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
mi_free(ptr as *mut c_void);
}

#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
mi_free(ptr as *mut c_void);
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
if layout.align() <= MIN_MIMALLOC_ALIGNMENT {
mi_zalloc(layout.size()) as *mut u8
} else {
mi_zalloc_aligned(layout.size(), layout.align()) as *mut u8
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Comment thread src/lib.rs
Comment on lines 113 to 168
#[test]
fn it_frees_allocated_memory() {
unsafe {
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;

let ptr = alloc.alloc(layout);
alloc.dealloc(ptr, layout);
}
let ptr = unsafe { alloc.alloc(layout) };
unsafe { alloc.dealloc(ptr, layout) };
}

#[test]
fn it_frees_allocated_big_memory() {
unsafe {
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;

let ptr = alloc.alloc(layout);
alloc.dealloc(ptr, layout);
}
let ptr = unsafe { alloc.alloc(layout) };
unsafe { alloc.dealloc(ptr, layout) };
}

#[test]
fn it_frees_zero_allocated_memory() {
unsafe {
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;

let ptr = alloc.alloc_zeroed(layout);
alloc.dealloc(ptr, layout);
}
let ptr = unsafe { alloc.alloc_zeroed(layout) };
unsafe { alloc.dealloc(ptr, layout) };
}

#[test]
fn it_frees_zero_allocated_big_memory() {
unsafe {
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;

let ptr = alloc.alloc_zeroed(layout);
alloc.dealloc(ptr, layout);
}
let ptr = unsafe { alloc.alloc_zeroed(layout) };
unsafe { alloc.dealloc(ptr, layout) };
}

#[test]
fn it_frees_reallocated_memory() {
unsafe {
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;
let layout = Layout::from_size_align(8, 8).unwrap();
let alloc = MiMalloc;

let ptr = alloc.alloc(layout);
let ptr = alloc.realloc(ptr, layout, 16);
alloc.dealloc(ptr, layout);
}
let ptr = unsafe { alloc.alloc(layout) };
let ptr = unsafe { alloc.realloc(ptr, layout, 16) };
unsafe { alloc.dealloc(ptr, layout) };
}

#[test]
fn it_frees_reallocated_big_memory() {
unsafe {
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;
let layout = Layout::from_size_align(1 << 20, 32).unwrap();
let alloc = MiMalloc;

let ptr = alloc.alloc(layout);
let ptr = alloc.realloc(ptr, layout, 2 << 20);
alloc.dealloc(ptr, layout);
}
let ptr = unsafe { alloc.alloc(layout) };
let ptr = unsafe { alloc.realloc(ptr, layout, 2 << 20) };
unsafe { alloc.dealloc(ptr, layout) };
}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not everything inside those blocks was unsafe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant