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