1 use std::mem;
2
3 use bytes::Buf;
4 use criterion::{Criterion, Throughput};
5 use prost::encoding::{decode_varint, encode_varint, encoded_len_varint};
6 use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng};
7
benchmark_varint(criterion: &mut Criterion, name: &str, mut values: Vec<u64>)8 fn benchmark_varint(criterion: &mut Criterion, name: &str, mut values: Vec<u64>) {
9 // Shuffle the values in a stable order.
10 values.shuffle(&mut StdRng::seed_from_u64(0));
11 let name = format!("varint/{}", name);
12
13 let encoded_len = values
14 .iter()
15 .cloned()
16 .map(encoded_len_varint)
17 .sum::<usize>() as u64;
18 let decoded_len = (values.len() * mem::size_of::<u64>()) as u64;
19
20 criterion
21 .benchmark_group(&name)
22 .bench_function("encode", {
23 let encode_values = values.clone();
24 move |b| {
25 let mut buf = Vec::<u8>::with_capacity(encode_values.len() * 10);
26 b.iter(|| {
27 buf.clear();
28 for &value in &encode_values {
29 encode_varint(value, &mut buf);
30 }
31 criterion::black_box(&buf);
32 })
33 }
34 })
35 .throughput(Throughput::Bytes(encoded_len));
36
37 criterion
38 .benchmark_group(&name)
39 .bench_function("decode", {
40 let decode_values = values.clone();
41
42 move |b| {
43 let mut buf = Vec::with_capacity(decode_values.len() * 10);
44 for &value in &decode_values {
45 encode_varint(value, &mut buf);
46 }
47
48 b.iter(|| {
49 let mut buf = &mut buf.as_slice();
50 while buf.has_remaining() {
51 let result = decode_varint(&mut buf);
52 debug_assert!(result.is_ok());
53 criterion::black_box(&result);
54 }
55 })
56 }
57 })
58 .throughput(Throughput::Bytes(decoded_len));
59
60 criterion
61 .benchmark_group(&name)
62 .bench_function("encoded_len", move |b| {
63 b.iter(|| {
64 let mut sum = 0;
65 for &value in &values {
66 sum += encoded_len_varint(value);
67 }
68 criterion::black_box(sum);
69 })
70 })
71 .throughput(Throughput::Bytes(decoded_len));
72 }
73
main()74 fn main() {
75 let mut criterion = Criterion::default().configure_from_args();
76
77 // Benchmark encoding and decoding 100 small (1 byte) varints.
78 benchmark_varint(&mut criterion, "small", (0..100).collect());
79
80 // Benchmark encoding and decoding 100 medium (5 byte) varints.
81 benchmark_varint(&mut criterion, "medium", (1 << 28..).take(100).collect());
82
83 // Benchmark encoding and decoding 100 large (10 byte) varints.
84 benchmark_varint(&mut criterion, "large", (1 << 63..).take(100).collect());
85
86 // Benchmark encoding and decoding 100 varints of mixed width (average 5.5 bytes).
87 benchmark_varint(
88 &mut criterion,
89 "mixed",
90 (0..10)
91 .flat_map(move |width| {
92 let exponent = width * 7;
93 (0..10).map(move |offset| offset + (1 << exponent))
94 })
95 .collect(),
96 );
97
98 criterion.final_summary();
99 }
100