Skip to content

Commit bd0654f

Browse files
authored
Rework benchmarks to make it easier to get assembly. (#297)
* Rename benches/mod.rs to benches/buffer.rs This naming makes more sense, especially if we add more benchmark files. Signed-off-by: Joe Richey <joerichey@google.com> * Rework benchmarks to make it easier to get assembly. This change: - Move the benchmarks from mod.rs to buffer.rs - Move the inner loop we benchmark into an `#[inline(never)]` function - Includes instructions for getting the ASM for a specific benchmark This should hopefully reduce the variance of these benchmarks and make it easier to figure out if we are emitting the assembly or IR we expect for a particular implementation. Signed-off-by: Joe Richey <joerichey@google.com> Signed-off-by: Joe Richey <joerichey@google.com>
1 parent 55ad4c4 commit bd0654f

File tree

2 files changed

+71
-64
lines changed

2 files changed

+71
-64
lines changed

benches/buffer.rs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#![feature(test, maybe_uninit_uninit_array_transpose)]
2+
extern crate test;
3+
4+
use std::mem::MaybeUninit;
5+
6+
// Call getrandom on a zero-initialized stack buffer
7+
#[inline(always)]
8+
fn bench_getrandom<const N: usize>() {
9+
let mut buf = [0u8; N];
10+
getrandom::getrandom(&mut buf).unwrap();
11+
test::black_box(&buf as &[u8]);
12+
}
13+
14+
// Call getrandom_uninit on an uninitialized stack buffer
15+
#[inline(always)]
16+
fn bench_getrandom_uninit<const N: usize>() {
17+
let mut uninit = [MaybeUninit::uninit(); N];
18+
let buf: &[u8] = getrandom::getrandom_uninit(&mut uninit).unwrap();
19+
test::black_box(buf);
20+
}
21+
22+
// We benchmark using #[inline(never)] "inner" functions for two reasons:
23+
// - Avoiding inlining reduces a source of variance when running benchmarks.
24+
// - It is _much_ easier to get the assembly or IR for the inner loop.
25+
//
26+
// For example, using cargo-show-asm (https://github.com/pacak/cargo-show-asm),
27+
// we can get the assembly for a particular benchmark's inner loop by running:
28+
// cargo asm --bench buffer --release buffer::p384::bench_getrandom::inner
29+
macro_rules! bench {
30+
( $name:ident, $size:expr ) => {
31+
pub mod $name {
32+
#[bench]
33+
pub fn bench_getrandom(b: &mut test::Bencher) {
34+
#[inline(never)]
35+
fn inner() {
36+
super::bench_getrandom::<{ $size }>()
37+
}
38+
39+
b.bytes = $size as u64;
40+
b.iter(inner);
41+
}
42+
#[bench]
43+
pub fn bench_getrandom_uninit(b: &mut test::Bencher) {
44+
#[inline(never)]
45+
fn inner() {
46+
super::bench_getrandom_uninit::<{ $size }>()
47+
}
48+
49+
b.bytes = $size as u64;
50+
b.iter(inner);
51+
}
52+
}
53+
};
54+
}
55+
56+
// 16 bytes (128 bits) is the size of an 128-bit AES key/nonce.
57+
bench!(aes128, 128 / 8);
58+
59+
// 32 bytes (256 bits) is the seed sized used for rand::thread_rng
60+
// and the `random` value in a ClientHello/ServerHello for TLS.
61+
// This is also the size of a 256-bit AES/HMAC/P-256/Curve25519 key
62+
// and/or nonce.
63+
bench!(p256, 256 / 8);
64+
65+
// A P-384/HMAC-384 key and/or nonce.
66+
bench!(p384, 384 / 8);
67+
68+
// Initializing larger buffers is not the primary use case of this library, as
69+
// this should normally be done by a userspace CSPRNG. However, we have a test
70+
// here to see the effects of a lower (amortized) syscall overhead.
71+
bench!(page, 4096);

benches/mod.rs

-64
This file was deleted.

0 commit comments

Comments
 (0)