Skip to content

Commit 4719b5f

Browse files
committed
Rework benchmarks
1 parent 033fc76 commit 4719b5f

File tree

1 file changed

+32
-82
lines changed

1 file changed

+32
-82
lines changed

benches/mod.rs

+32-82
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,67 @@
11
#![feature(test)]
22
extern crate test;
33

4-
use std::{
5-
alloc::{alloc_zeroed, dealloc, Layout},
6-
mem::{self, MaybeUninit},
7-
ptr::NonNull,
8-
};
4+
use core::mem::MaybeUninit;
95

10-
// AlignedBuffer is like a Box<[u8; N]> except that it is always N-byte aligned
11-
struct AlignedBuffer<const N: usize>(NonNull<[u8; N]>);
12-
13-
impl<const N: usize> AlignedBuffer<N> {
14-
fn layout() -> Layout {
15-
Layout::from_size_align(N, N).unwrap()
16-
}
17-
18-
fn new() -> Self {
19-
let p = unsafe { alloc_zeroed(Self::layout()) } as *mut [u8; N];
20-
Self(NonNull::new(p).unwrap())
21-
}
22-
23-
fn buf(&mut self) -> &mut [u8; N] {
24-
unsafe { self.0.as_mut() }
25-
}
26-
}
27-
28-
impl<const N: usize> Drop for AlignedBuffer<N> {
29-
fn drop(&mut self) {
30-
unsafe { dealloc(self.0.as_ptr() as *mut u8, Self::layout()) }
31-
}
32-
}
33-
34-
// Used to benchmark the throughput of getrandom in an optimal scenario.
35-
// The buffer is hot, and does not require initialization.
6+
// Used to benchmark the throughput of getrandom where we have to initialize the
7+
// buffer every time.
368
#[inline(always)]
379
fn bench<const N: usize>(b: &mut test::Bencher) {
38-
let mut ab = AlignedBuffer::<N>::new();
39-
let buf = ab.buf();
40-
b.iter(|| {
41-
getrandom::getrandom(&mut buf[..]).unwrap();
42-
test::black_box(&buf);
43-
});
4410
b.bytes = N as u64;
45-
}
46-
47-
// Used to benchmark the throughput of getrandom is a slightly less optimal
48-
// scenario. The buffer is still hot, but requires initialization.
49-
#[inline(always)]
50-
fn bench_with_init<const N: usize>(b: &mut test::Bencher) {
51-
let mut ab = AlignedBuffer::<N>::new();
52-
let buf = ab.buf();
5311
b.iter(|| {
54-
for byte in buf.iter_mut() {
55-
*byte = 0;
56-
}
57-
getrandom::getrandom(&mut buf[..]).unwrap();
12+
let mut buf = [0u8; N];
13+
getrandom::getrandom(&mut buf).unwrap();
5814
test::black_box(&buf);
5915
});
60-
b.bytes = N as u64;
6116
}
6217

63-
// Used to benchmark the benefit of `getrandom_uninit` compared to
64-
// zero-initializing a buffer and then using `getrandom` (`bench_with_init`
65-
// above).
18+
// Used to benchmark getrandom_uninit, where we don't need to initilize the
19+
// buffer each time.
6620
#[inline(always)]
6721
fn bench_uninit<const N: usize>(b: &mut test::Bencher) {
68-
let mut ab = AlignedBuffer::<N>::new();
69-
let buf = ab.buf();
70-
// SAFETY: `buf` doesn't escape this scope.
71-
let buf = unsafe { slice_as_uninit_mut(buf) };
22+
b.bytes = N as u64;
7223
b.iter(|| {
73-
let _ = getrandom::getrandom_uninit_slice(buf);
74-
})
24+
let mut buf = [MaybeUninit::<u8>::uninit(); N];
25+
let buf: &[u8] = getrandom::getrandom_uninit_slice(&mut buf).unwrap();
26+
test::black_box(buf);
27+
});
7528
}
7629

77-
// 32 bytes (256-bit) is the seed sized used for rand::thread_rng
78-
const SEED: usize = 32;
7930
// Common size of a page, 4 KiB
8031
const PAGE: usize = 4096;
8132
// Large buffer to get asymptotic performance, 2 MiB
8233
const LARGE: usize = 1 << 21;
8334

8435
#[bench]
85-
fn bench_seed(b: &mut test::Bencher) {
86-
bench::<SEED>(b);
36+
fn bench_16(b: &mut test::Bencher) {
37+
bench::<16>(b);
8738
}
8839
#[bench]
89-
fn bench_seed_init(b: &mut test::Bencher) {
90-
bench_with_init::<SEED>(b);
40+
fn bench_16_uninit(b: &mut test::Bencher) {
41+
bench_uninit::<16>(b);
42+
}
43+
44+
#[bench]
45+
fn bench_32(b: &mut test::Bencher) {
46+
bench::<32>(b);
9147
}
9248
#[bench]
93-
fn bench_seed_uninit(b: &mut test::Bencher) {
94-
bench_uninit::<SEED>(b);
49+
fn bench_32_uninit(b: &mut test::Bencher) {
50+
bench_uninit::<32>(b);
9551
}
9652

9753
#[bench]
98-
fn bench_page(b: &mut test::Bencher) {
99-
bench::<PAGE>(b);
54+
fn bench_256(b: &mut test::Bencher) {
55+
bench::<256>(b);
10056
}
10157
#[bench]
102-
fn bench_page_init(b: &mut test::Bencher) {
103-
bench_with_init::<PAGE>(b);
58+
fn bench_256_uninit(b: &mut test::Bencher) {
59+
bench_uninit::<256>(b);
60+
}
61+
62+
#[bench]
63+
fn bench_page(b: &mut test::Bencher) {
64+
bench::<PAGE>(b);
10465
}
10566
#[bench]
10667
fn bench_page_uninit(b: &mut test::Bencher) {
@@ -112,17 +73,6 @@ fn bench_large(b: &mut test::Bencher) {
11273
bench::<LARGE>(b);
11374
}
11475
#[bench]
115-
fn bench_large_init(b: &mut test::Bencher) {
116-
bench_with_init::<LARGE>(b);
117-
}
118-
#[bench]
11976
fn bench_large_uninit(b: &mut test::Bencher) {
12077
bench_uninit::<LARGE>(b);
12178
}
122-
123-
// TODO: Safety note.
124-
#[inline(always)]
125-
unsafe fn slice_as_uninit_mut<T>(slice: &mut [T]) -> &mut [MaybeUninit<T>] {
126-
// SAFETY: `MaybeUninit<T>` is guaranteed to be layout-compatible with `T`.
127-
mem::transmute(slice)
128-
}

0 commit comments

Comments
 (0)