2017-11-27 18:07:57 +00:00
|
|
|
//! Benchmarks the cost of the different allocation functions by doing a
|
|
|
|
//! roundtrip (allocate, deallocate).
|
2018-11-15 15:16:15 +00:00
|
|
|
#![feature(test, allocator_api)]
|
|
|
|
#![cfg(feature = "alloc_trait")]
|
2017-11-27 18:07:57 +00:00
|
|
|
|
|
|
|
extern crate jemallocator;
|
|
|
|
extern crate libc;
|
2018-11-15 15:16:15 +00:00
|
|
|
extern crate paste;
|
2018-10-30 19:34:36 +00:00
|
|
|
extern crate test;
|
2017-11-27 18:07:57 +00:00
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
use jemallocator::{ffi::MALLOCX_ALIGN, Jemalloc};
|
2018-10-30 19:34:36 +00:00
|
|
|
use libc::c_int;
|
2018-11-15 15:16:15 +00:00
|
|
|
use std::{
|
|
|
|
alloc::{Alloc, Excess, Layout},
|
|
|
|
ptr,
|
|
|
|
};
|
2017-11-27 18:07:57 +00:00
|
|
|
use test::Bencher;
|
|
|
|
|
|
|
|
#[global_allocator]
|
|
|
|
static A: Jemalloc = Jemalloc;
|
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
// FIXME: replace with jemallocator::layout_to_flags
|
2018-10-30 19:34:36 +00:00
|
|
|
#[cfg(all(any(
|
|
|
|
target_arch = "arm",
|
|
|
|
target_arch = "mips",
|
|
|
|
target_arch = "mipsel",
|
|
|
|
target_arch = "powerpc"
|
|
|
|
)))]
|
2017-11-27 18:07:57 +00:00
|
|
|
const MIN_ALIGN: usize = 8;
|
2018-10-30 19:34:36 +00:00
|
|
|
#[cfg(all(any(
|
|
|
|
target_arch = "x86",
|
|
|
|
target_arch = "x86_64",
|
|
|
|
target_arch = "aarch64",
|
|
|
|
target_arch = "powerpc64",
|
2018-11-15 15:16:15 +00:00
|
|
|
target_arch = "powerpc64le",
|
|
|
|
target_arch = "mips64",
|
|
|
|
target_arch = "s390x",
|
|
|
|
target_arch = "sparc64"
|
2018-10-30 19:34:36 +00:00
|
|
|
)))]
|
2017-11-27 18:07:57 +00:00
|
|
|
const MIN_ALIGN: usize = 16;
|
|
|
|
|
|
|
|
fn layout_to_flags(layout: &Layout) -> c_int {
|
|
|
|
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
|
|
|
|
0
|
|
|
|
} else {
|
2018-11-15 15:16:15 +00:00
|
|
|
MALLOCX_ALIGN(layout.align())
|
2017-11-27 18:07:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
macro_rules! rt {
|
|
|
|
($size:expr, $align:expr) => {
|
|
|
|
paste::item! {
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_mallocx_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
use jemallocator::ffi as jemalloc;
|
|
|
|
let flags = layout_to_flags(&Layout::from_size_align($size, $align).unwrap());
|
|
|
|
let ptr = jemalloc::mallocx($size, flags);
|
|
|
|
test::black_box(ptr);
|
|
|
|
jemalloc::sdallocx(ptr, $size, flags);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_mallocx_nallocx_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
use jemallocator::ffi as jemalloc;
|
|
|
|
let flags = layout_to_flags(&Layout::from_size_align($size, $align).unwrap());
|
|
|
|
let ptr = jemalloc::mallocx($size, flags);
|
|
|
|
test::black_box(ptr);
|
|
|
|
let rsz = jemalloc::nallocx($size, flags);
|
|
|
|
test::black_box(rsz);
|
|
|
|
jemalloc::sdallocx(ptr, rsz, flags);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_alloc_layout_checked_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align($size, $align).unwrap();
|
|
|
|
let ptr = Jemalloc.alloc(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
Jemalloc.dealloc(ptr, layout);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_alloc_layout_unchecked_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align_unchecked($size, $align);
|
|
|
|
let ptr = Jemalloc.alloc(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
Jemalloc.dealloc(ptr, layout);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_alloc_excess_unused_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align($size, $align).unwrap();
|
|
|
|
let Excess(ptr, _) = Jemalloc.alloc_excess(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
2017-11-27 18:07:57 +00:00
|
|
|
Jemalloc.dealloc(ptr, layout);
|
2018-11-15 15:16:15 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_alloc_excess_used_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align($size, $align).unwrap();
|
|
|
|
let Excess(ptr, excess) = Jemalloc.alloc_excess(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
test::black_box(excess);
|
|
|
|
Jemalloc.dealloc(ptr, layout);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_mallocx_zeroed_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
use jemallocator::ffi as jemalloc;
|
|
|
|
let flags = layout_to_flags(&Layout::from_size_align($size, $align).unwrap());
|
|
|
|
let ptr = jemalloc::mallocx($size, flags | jemalloc::MALLOCX_ZERO);
|
|
|
|
test::black_box(ptr);
|
|
|
|
jemalloc::sdallocx(ptr, $size, flags);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_calloc_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
use jemallocator::ffi as jemalloc;
|
|
|
|
let flags = layout_to_flags(&Layout::from_size_align($size, $align).unwrap());
|
|
|
|
test::black_box(flags);
|
|
|
|
let ptr = jemalloc::calloc(1, $size);
|
|
|
|
test::black_box(ptr);
|
|
|
|
jemalloc::sdallocx(ptr, $size, 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_realloc_naive_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align($size, $align).unwrap();
|
|
|
|
let ptr = Jemalloc.alloc(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
|
|
|
|
// navie realloc:
|
|
|
|
let new_layout = Layout::from_size_align(2 * $size, $align).unwrap();
|
|
|
|
let ptr = {
|
|
|
|
let new_ptr = Jemalloc.alloc(new_layout.clone()).unwrap();
|
|
|
|
ptr::copy_nonoverlapping(ptr.as_ptr() as *const u8, new_ptr.as_ptr(), layout.size());
|
|
|
|
Jemalloc.dealloc(ptr, layout);
|
|
|
|
new_ptr
|
|
|
|
};
|
|
|
|
test::black_box(ptr);
|
|
|
|
|
|
|
|
Jemalloc.dealloc(ptr, new_layout);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_realloc_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align($size, $align).unwrap();
|
|
|
|
let ptr = Jemalloc.alloc(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
|
|
|
|
let new_layout = Layout::from_size_align(2 * $size, $align).unwrap();
|
|
|
|
let ptr = Jemalloc.realloc(ptr, layout, new_layout.size()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
|
|
|
|
Jemalloc.dealloc(ptr, new_layout);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_realloc_excess_unused_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align($size, $align).unwrap();
|
|
|
|
let ptr = Jemalloc.alloc(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
|
|
|
|
let new_layout = Layout::from_size_align(2 * $size, $align).unwrap();
|
|
|
|
let Excess(ptr, _) = Jemalloc
|
|
|
|
.realloc_excess(ptr, layout, new_layout.size())
|
|
|
|
.unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
|
|
|
|
Jemalloc.dealloc(ptr, new_layout);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn [<rt_realloc_excess_used_size_ $size _align_ $align>](b: &mut Bencher) {
|
|
|
|
b.iter(|| unsafe {
|
|
|
|
let layout = Layout::from_size_align($size, $align).unwrap();
|
|
|
|
let ptr = Jemalloc.alloc(layout.clone()).unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
|
|
|
|
let new_layout = Layout::from_size_align(2 * $size, $align).unwrap();
|
|
|
|
let Excess(ptr, excess) = Jemalloc
|
|
|
|
.realloc_excess(ptr, layout, new_layout.size())
|
|
|
|
.unwrap();
|
|
|
|
test::black_box(ptr);
|
|
|
|
test::black_box(excess);
|
|
|
|
|
|
|
|
Jemalloc.dealloc(ptr, new_layout);
|
|
|
|
});
|
|
|
|
}
|
2017-11-27 18:07:57 +00:00
|
|
|
|
|
|
|
}
|
2018-10-30 19:34:36 +00:00
|
|
|
};
|
2018-11-15 15:16:15 +00:00
|
|
|
([$($size:expr),*]) => {
|
|
|
|
$(
|
|
|
|
rt!($size, 1);
|
|
|
|
rt!($size, 2);
|
|
|
|
rt!($size, 4);
|
|
|
|
rt!($size, 8);
|
|
|
|
rt!($size, 16);
|
|
|
|
rt!($size, 32);
|
|
|
|
)*
|
|
|
|
}
|
2017-11-27 18:07:57 +00:00
|
|
|
}
|
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
// Powers of two
|
|
|
|
mod pow2 {
|
|
|
|
use super::*;
|
2017-11-27 18:07:57 +00:00
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
rt!([
|
|
|
|
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072,
|
|
|
|
4194304
|
|
|
|
]);
|
2017-11-27 18:07:57 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
mod even {
|
|
|
|
use super::*;
|
2017-11-27 18:07:57 +00:00
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
rt!([10, 100, 1000, 10000, 100000, 1000000]);
|
2017-11-27 18:07:57 +00:00
|
|
|
}
|
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
mod odd {
|
|
|
|
use super::*;
|
|
|
|
rt!([9, 99, 999, 9999, 99999, 999999]);
|
2017-11-27 18:07:57 +00:00
|
|
|
}
|
|
|
|
|
2018-11-15 15:16:15 +00:00
|
|
|
mod primes {
|
|
|
|
use super::*;
|
|
|
|
rt!([
|
|
|
|
3, 7, 13, 17, 31, 61, 96, 127, 257, 509, 1021, 2039, 4093, 8191, 16381, 32749, 65537,
|
|
|
|
131071, 4194301
|
|
|
|
]);
|
|
|
|
}
|