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); |
72 | |