1 #![allow(unknown_lints)]
2 
3 use criterion::{criterion_group, criterion_main, Criterion, BatchSize, Throughput, ParameterizedBenchmark};
4 use rand::prelude::*;
5 
6 
7 const SIZES: &[usize] = &[3, 16, 64, 256, 1024];
8 
rand_enc_input(sz: usize) -> (Vec<u8>, base16::EncConfig)9 fn rand_enc_input(sz: usize) -> (Vec<u8>, base16::EncConfig) {
10     let mut rng = thread_rng();
11     let mut vec = vec![0u8; sz];
12     let cfg = if rng.gen::<bool>() {
13         base16::EncodeUpper
14     } else {
15         base16::EncodeLower
16     };
17     rng.fill_bytes(&mut vec);
18     (vec, cfg)
19 }
20 
batch_size_for_input(i: usize) -> BatchSize21 fn batch_size_for_input(i: usize) -> BatchSize {
22     if i < 1024 {
23         BatchSize::SmallInput
24     } else {
25         BatchSize::LargeInput
26     }
27 }
28 
bench_encode(c: &mut Criterion)29 fn bench_encode(c: &mut Criterion) {
30     c.bench(
31         "encode to fresh string",
32         ParameterizedBenchmark::new(
33             "encode_config",
34             |b, items| {
35                 b.iter_batched(
36                     || rand_enc_input(*items),
37                     |(input, enc)| base16::encode_config(&input, enc),
38                     batch_size_for_input(*items),
39                 )
40             },
41             SIZES.iter().cloned(),
42         ).throughput(|bytes| Throughput::Bytes(*bytes as u32)),
43     );
44 
45     c.bench(
46         "encode to preallocated string",
47         ParameterizedBenchmark::new(
48             "encode_config_buf",
49             |b, items| {
50                 b.iter_batched(
51                     || (rand_enc_input(*items), String::with_capacity(2 * *items)),
52                     |((input, enc), mut buf)| {
53                         buf.truncate(0);
54                         base16::encode_config_buf(&input, enc, &mut buf)
55                     },
56                     batch_size_for_input(*items),
57                 )
58             },
59             SIZES.iter().cloned(),
60         ).throughput(|bytes| Throughput::Bytes(*bytes as u32)),
61     );
62 
63     c.bench(
64         "encode to slice",
65         ParameterizedBenchmark::new(
66             "encode_config_slice",
67             |b, items| {
68                 b.iter_batched(
69                     || (rand_enc_input(*items), vec![0u8; 2 * *items]),
70                     |((input, enc), mut dst)| {
71                         base16::encode_config_slice(&input, enc, &mut dst)
72                     },
73                     batch_size_for_input(*items),
74                 )
75             },
76             SIZES.iter().cloned(),
77         ).throughput(|bytes| Throughput::Bytes(*bytes as u32)),
78     );
79 }
80 
rand_hex_string(size: usize) -> String81 fn rand_hex_string(size: usize) -> String {
82     let mut rng = thread_rng();
83     let mut s = String::with_capacity(size);
84     let chars: &[u8] = b"0123456789abcdefABCDEF";
85     while s.len() < size {
86         s.push(*chars.choose(&mut rng).unwrap() as char);
87     }
88     s
89 }
90 
bench_decode(c: &mut Criterion)91 fn bench_decode(c: &mut Criterion) {
92     c.bench(
93         "decode to fresh vec",
94         ParameterizedBenchmark::new(
95             "decode",
96             |b, items| {
97                 b.iter_batched(
98                     || rand_hex_string(*items),
99                     |input| base16::decode(&input),
100                     batch_size_for_input(*items),
101                 )
102             },
103             SIZES.iter().cloned(),
104         ).throughput(|bytes| Throughput::Bytes(*bytes as u32 * 2)),
105     );
106 
107     c.bench(
108         "decode to preallocated vec",
109         ParameterizedBenchmark::new(
110             "decode_buf",
111             |b, items| {
112                 b.iter_batched(
113                     || (rand_hex_string(*items), Vec::with_capacity(*items)),
114                     |(input, mut buf)| {
115                         buf.truncate(0);
116                         base16::decode_buf(&input, &mut buf)
117                     },
118                     batch_size_for_input(*items),
119                 )
120             },
121             SIZES.iter().cloned(),
122         ).throughput(|bytes| Throughput::Bytes(*bytes as u32 * 2)),
123     );
124 
125     c.bench(
126         "decode to slice",
127         ParameterizedBenchmark::new(
128             "decode_slice",
129             |b, items| {
130                 b.iter_batched(
131                     || (rand_hex_string(*items), vec![0u8; *items]),
132                     |(input, mut buf)| {
133                         base16::decode_slice(&input, &mut buf)
134                     },
135                     batch_size_for_input(*items),
136                 )
137             },
138             SIZES.iter().cloned(),
139         ).throughput(|bytes| Throughput::Bytes(*bytes as u32 * 2)),
140     );
141 }
142 
143 
144 criterion_group!(benches, bench_encode, bench_decode);
145 criterion_main!(benches);
146