benches.rs 6.55 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Copyright 2019 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

15
use std::{time::Duration, any::type_name, convert::{TryFrom, TryInto}};
16

17
#[cfg(feature = "bit-vec")]
18
use bitvec::{vec::BitVec, order::Lsb0};
Qinxuan Chen's avatar
Qinxuan Chen committed
19
20
21
use criterion::{Criterion, black_box, Bencher, criterion_group, criterion_main};
use parity_scale_codec::*;
use parity_scale_codec_derive::{Encode, Decode};
22
23

fn array_vec_write_u128(b: &mut Bencher) {
24
	b.iter(|| {
25
		for b in 0..black_box(1_000_000) {
26
27
			let a = 0xffff_ffff_ffff_ffff_ffff_u128;
			Compact(a ^ b).using_encoded(|x| {
28
				black_box(x).len()
29
30
31
32
33
			});
		}
	});
}

34
35
36
fn test_vec<F: Fn(&mut Vec<u8>, &[u8])>(b: &mut Bencher, f: F) {
	let f = black_box(f);
	let x = black_box([0xff; 10240]);
37
38

	b.iter(|| {
39
		for _b in 0..black_box(10_000) {
40
41
42
43
44
45
			let mut vec = Vec::<u8>::new();
			f(&mut vec, &x);
		}
	});
}

46
fn vec_write_as_output(b: &mut Bencher) {
47
48
49
50
51
	test_vec(b, |vec, a| {
		Output::write(vec, a);
	});
}

52
fn vec_extend(b: &mut Bencher) {
53
54
55
56
57
	test_vec(b, |vec, a| {
		vec.extend(a);
	});
}

58
fn vec_extend_from_slice(b: &mut Bencher) {
59
60
61
62
63
	test_vec(b, |vec, a| {
		vec.extend_from_slice(a);
	});
}

64
65
66
67
68
69
70
71
72
73
74
75
struct NoLimitInput<'a>(&'a [u8]);

impl<'a> Input for NoLimitInput<'a> {
	fn remaining_len(&mut self) -> Result<Option<usize>, Error> {
		Ok(None)
	}

	fn read(&mut self, into: &mut [u8]) -> Result<(), Error> {
		self.0.read(into)
	}
}

76
77
78
79
80
#[derive(Encode, Decode)]
enum Event {
	ComplexEvent(Vec<u8>, u32, i32, u128, i8),
}

81
fn vec_append_with_decode_and_encode(b: &mut Bencher) {
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
	let data = b"PCX";

	b.iter(|| {
		let mut encoded_events_vec = Vec::new();
		for _ in 0..1000 {
			let mut events = Vec::<Event>::decode(&mut &encoded_events_vec[..])
				.unwrap_or_default();

			events.push(Event::ComplexEvent(data.to_vec(), 4, 5, 6, 9));

			encoded_events_vec = events.encode();
		}
	})
}

97
fn vec_append_with_encode_append(b: &mut Bencher) {
98
99
100
101
102
103
104
105
106
	let data = b"PCX";

	b.iter(|| {
		let mut encoded_events_vec;

		let events = vec![Event::ComplexEvent(data.to_vec(), 4, 5, 6, 9)];
		encoded_events_vec = events.encode();

		for _ in 1..1000 {
Qinxuan Chen's avatar
Qinxuan Chen committed
107
			encoded_events_vec = <Vec<Event> as EncodeAppend>::append_or_new(
108
109
110
111
112
				encoded_events_vec,
				&[Event::ComplexEvent(data.to_vec(), 4, 5, 6, 9)],
			).unwrap();
		}
	});
113
114
}

115
116
117
fn encode_decode_vec<T: TryFrom<u8> + Codec>(c: &mut Criterion) where T::Error: std::fmt::Debug {
	c.bench_function_over_inputs(&format!("vec_encode_{}", type_name::<T>()), |b, &vec_size| {
		let vec: Vec<T> = (0..=127u8)
118
119
			.cycle()
			.take(vec_size)
120
			.map(|v| v.try_into().unwrap())
121
122
123
124
			.collect();

		let vec = black_box(vec);
		b.iter(|| vec.encode())
125
	}, vec![1, 2, 5, 32, 1024, 2048, 16384]);
126

127
128
	c.bench_function_over_inputs(&format!("vec_decode_{}", type_name::<T>()), |b, &vec_size| {
		let vec: Vec<T> = (0..=127u8)
129
130
			.cycle()
			.take(vec_size)
131
			.map(|v| v.try_into().unwrap())
132
133
134
135
136
137
			.collect();

		let vec = vec.encode();

		let vec = black_box(vec);
		b.iter(|| {
138
			let _: Vec<T> = Decode::decode(&mut &vec[..]).unwrap();
139
		})
140
	}, vec![1, 2, 5, 32, 1024, 2048, 16384]);
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

	c.bench_function_over_inputs(&format!("vec_decode_no_limit_{}", type_name::<T>()), |b, &vec_size| {
		let vec: Vec<T> = (0..=127u8)
			.cycle()
			.take(vec_size)
			.map(|v| v.try_into().unwrap())
			.collect();

		let vec = vec.encode();

		let vec = black_box(vec);
		b.iter(|| {
			let _: Vec<T> = Decode::decode(&mut NoLimitInput(&vec[..])).unwrap();
		})
	}, vec![16384, 131072]);
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
}

fn encode_decode_complex_type(c: &mut Criterion) {
	#[derive(Encode, Decode, Clone)]
	struct ComplexType {
		_val: u32,
		_other_val: u128,
		_vec: Vec<u32>,
	}

	let complex_types = vec![
		ComplexType { _val: 3, _other_val: 345634635, _vec: vec![1, 2, 3, 5, 6, 7] },
		ComplexType { _val: 1000, _other_val: 0980345634635, _vec: vec![1, 2, 3, 5, 6, 7] },
		ComplexType { _val: 43564, _other_val: 342342345634635, _vec: vec![1, 2, 3, 5, 6, 7] },
	];
	let complex_types2 = complex_types.clone();

	c.bench_function_over_inputs("vec_encode_complex_type", move |b, &vec_size| {
		let vec: Vec<ComplexType> = complex_types.clone().into_iter().cycle().take(vec_size).collect();

		let vec = black_box(vec);
		b.iter(|| vec.encode())
	}, vec![1, 2, 5, 32, 1024, 2048, 16384]);

	c.bench_function_over_inputs("vec_decode_complex_type", move |b, &vec_size| {
		let vec: Vec<ComplexType> = complex_types2.clone().into_iter().cycle().take(vec_size).collect();

		let vec = vec.encode();

		let vec = black_box(vec);
		b.iter(|| {
			let _: Vec<ComplexType> = Decode::decode(&mut &vec[..]).unwrap();
		})
	}, vec![1, 2, 5, 32, 1024, 2048, 16384]);
190
191
192
193
194
195
196
197
198
199
200
}

fn bench_fn(c: &mut Criterion) {
	c.bench_function("vec_write_as_output", vec_write_as_output);
	c.bench_function("vec_extend", vec_extend);
	c.bench_function("vec_extend_from_slice", vec_extend_from_slice);
	c.bench_function("vec_append_with_decode_and_encode", vec_append_with_decode_and_encode);
	c.bench_function("vec_append_with_encode_append", vec_append_with_encode_append);
	c.bench_function("array_vec_write_u128", array_vec_write_u128);
}

201
fn encode_decode_bitvec_u8(c: &mut Criterion) {
202
203
204
	let _ = c;

	#[cfg(feature = "bit-vec")]
205
	c.bench_function_over_inputs("bitvec_u8_encode - BitVec<u8>", |b, &size| {
206
		let vec: BitVec<Lsb0, u8> = [true, false]
207
208
209
210
211
212
213
214
215
216
			.iter()
			.cloned()
			.cycle()
			.take(size)
			.collect();

		let vec = black_box(vec);
		b.iter(|| vec.encode())
	}, vec![1, 2, 5, 32, 1024]);

217
	#[cfg(feature = "bit-vec")]
218
	c.bench_function_over_inputs("bitvec_u8_decode - BitVec<u8>", |b, &size| {
219
		let vec: BitVec<Lsb0, u8> = [true, false]
220
221
222
223
224
225
226
227
228
229
			.iter()
			.cloned()
			.cycle()
			.take(size)
			.collect();

		let vec = vec.encode();

		let vec = black_box(vec);
		b.iter(|| {
230
			let _: BitVec<Lsb0, u8> = Decode::decode(&mut &vec[..]).unwrap();
231
232
233
234
		})
	}, vec![1, 2, 5, 32, 1024]);
}

235
236
237
criterion_group!{
	name = benches;
	config = Criterion::default().warm_up_time(Duration::from_millis(500)).without_plots();
238
239
240
	targets = encode_decode_vec::<u8>, encode_decode_vec::<u16>, encode_decode_vec::<u32>, encode_decode_vec::<u64>,
			encode_decode_vec::<i8>, encode_decode_vec::<i16>, encode_decode_vec::<i32>, encode_decode_vec::<i64>,
			bench_fn, encode_decode_bitvec_u8, encode_decode_complex_type
241
242
}
criterion_main!(benches);