|
1 | | -use criterion::{self, criterion_group, criterion_main, Criterion}; |
2 | | -use pretty_assertions::assert_eq; |
3 | | -use quick_xml::events::Event; |
4 | | -use quick_xml::name::QName; |
5 | | -use quick_xml::Reader; |
| 1 | +use criterion::criterion_main; |
6 | 2 |
|
7 | | -static SAMPLE: &[u8] = include_bytes!("../tests/documents/sample_rss.xml"); |
8 | | -static PLAYERS: &[u8] = include_bytes!("../tests/documents/players.xml"); |
| 3 | +mod macrobenches; |
| 4 | +mod microbenches; |
9 | 5 |
|
10 | | -/// Benchmarks the `Reader::read_event` function with all XML well-formless |
11 | | -/// checks disabled (with and without trimming content of #text nodes) |
12 | | -fn read_event(c: &mut Criterion) { |
13 | | - let mut group = c.benchmark_group("read_event"); |
14 | | - group.bench_function("trim_text = false", |b| { |
15 | | - b.iter(|| { |
16 | | - let mut r = Reader::from_reader(SAMPLE); |
17 | | - r.check_end_names(false).check_comments(false); |
18 | | - let mut count = criterion::black_box(0); |
19 | | - let mut buf = Vec::new(); |
20 | | - loop { |
21 | | - match r.read_event(&mut buf) { |
22 | | - Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1, |
23 | | - Ok(Event::Eof) => break, |
24 | | - _ => (), |
25 | | - } |
26 | | - buf.clear(); |
27 | | - } |
28 | | - assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml"); |
29 | | - }) |
30 | | - }); |
31 | | - |
32 | | - group.bench_function("trim_text = true", |b| { |
33 | | - b.iter(|| { |
34 | | - let mut r = Reader::from_reader(SAMPLE); |
35 | | - r.check_end_names(false) |
36 | | - .check_comments(false) |
37 | | - .trim_text(true); |
38 | | - let mut count = criterion::black_box(0); |
39 | | - let mut buf = Vec::new(); |
40 | | - loop { |
41 | | - match r.read_event(&mut buf) { |
42 | | - Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1, |
43 | | - Ok(Event::Eof) => break, |
44 | | - _ => (), |
45 | | - } |
46 | | - buf.clear(); |
47 | | - } |
48 | | - assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml"); |
49 | | - }); |
50 | | - }); |
51 | | - group.finish(); |
52 | | -} |
53 | | - |
54 | | -/// Benchmarks the `Reader::read_namespaced_event` function with all XML well-formless |
55 | | -/// checks disabled (with and without trimming content of #text nodes) |
56 | | -fn read_namespaced_event(c: &mut Criterion) { |
57 | | - let mut group = c.benchmark_group("read_namespaced_event"); |
58 | | - group.bench_function("trim_text = false", |b| { |
59 | | - b.iter(|| { |
60 | | - let mut r = Reader::from_reader(SAMPLE); |
61 | | - r.check_end_names(false).check_comments(false); |
62 | | - let mut count = criterion::black_box(0); |
63 | | - let mut buf = Vec::new(); |
64 | | - let mut ns_buf = Vec::new(); |
65 | | - loop { |
66 | | - match r.read_namespaced_event(&mut buf, &mut ns_buf) { |
67 | | - Ok((_, Event::Start(_))) | Ok((_, Event::Empty(_))) => count += 1, |
68 | | - Ok((_, Event::Eof)) => break, |
69 | | - _ => (), |
70 | | - } |
71 | | - buf.clear(); |
72 | | - } |
73 | | - assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml"); |
74 | | - }); |
75 | | - }); |
76 | | - |
77 | | - group.bench_function("trim_text = true", |b| { |
78 | | - b.iter(|| { |
79 | | - let mut r = Reader::from_reader(SAMPLE); |
80 | | - r.check_end_names(false) |
81 | | - .check_comments(false) |
82 | | - .trim_text(true); |
83 | | - let mut count = criterion::black_box(0); |
84 | | - let mut buf = Vec::new(); |
85 | | - let mut ns_buf = Vec::new(); |
86 | | - loop { |
87 | | - match r.read_namespaced_event(&mut buf, &mut ns_buf) { |
88 | | - Ok((_, Event::Start(_))) | Ok((_, Event::Empty(_))) => count += 1, |
89 | | - Ok((_, Event::Eof)) => break, |
90 | | - _ => (), |
91 | | - } |
92 | | - buf.clear(); |
93 | | - } |
94 | | - assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml"); |
95 | | - }); |
96 | | - }); |
97 | | - group.finish(); |
98 | | -} |
99 | | - |
100 | | -/// Benchmarks the `BytesText::unescaped()` method (includes time of `read_event` |
101 | | -/// benchmark) |
102 | | -fn bytes_text_unescaped(c: &mut Criterion) { |
103 | | - let mut group = c.benchmark_group("BytesText::unescaped"); |
104 | | - group.bench_function("trim_text = false", |b| { |
105 | | - b.iter(|| { |
106 | | - let mut buf = Vec::new(); |
107 | | - let mut r = Reader::from_reader(SAMPLE); |
108 | | - r.check_end_names(false).check_comments(false); |
109 | | - let mut count = criterion::black_box(0); |
110 | | - let mut nbtxt = criterion::black_box(0); |
111 | | - loop { |
112 | | - match r.read_event(&mut buf) { |
113 | | - Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1, |
114 | | - Ok(Event::Text(ref e)) => nbtxt += e.unescaped().unwrap().len(), |
115 | | - Ok(Event::Eof) => break, |
116 | | - _ => (), |
117 | | - } |
118 | | - buf.clear(); |
119 | | - } |
120 | | - assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml"); |
121 | | - |
122 | | - // Windows has \r\n instead of \n |
123 | | - #[cfg(windows)] |
124 | | - assert_eq!( |
125 | | - nbtxt, 67661, |
126 | | - "Overall length (in bytes) of all text contents of ./tests/documents/sample_rss.xml" |
127 | | - ); |
128 | | - |
129 | | - #[cfg(not(windows))] |
130 | | - assert_eq!( |
131 | | - nbtxt, 66277, |
132 | | - "Overall length (in bytes) of all text contents of ./tests/documents/sample_rss.xml" |
133 | | - ); |
134 | | - }); |
135 | | - }); |
136 | | - |
137 | | - group.bench_function("trim_text = true", |b| { |
138 | | - b.iter(|| { |
139 | | - let mut buf = Vec::new(); |
140 | | - let mut r = Reader::from_reader(SAMPLE); |
141 | | - r.check_end_names(false) |
142 | | - .check_comments(false) |
143 | | - .trim_text(true); |
144 | | - let mut count = criterion::black_box(0); |
145 | | - let mut nbtxt = criterion::black_box(0); |
146 | | - loop { |
147 | | - match r.read_event(&mut buf) { |
148 | | - Ok(Event::Start(_)) | Ok(Event::Empty(_)) => count += 1, |
149 | | - Ok(Event::Text(ref e)) => nbtxt += e.unescaped().unwrap().len(), |
150 | | - Ok(Event::Eof) => break, |
151 | | - _ => (), |
152 | | - } |
153 | | - buf.clear(); |
154 | | - } |
155 | | - assert_eq!(count, 1550, "Overall tag count in ./tests/documents/sample_rss.xml"); |
156 | | - |
157 | | - // Windows has \r\n instead of \n |
158 | | - #[cfg(windows)] |
159 | | - assert_eq!( |
160 | | - nbtxt, 50334, |
161 | | - "Overall length (in bytes) of all text contents of ./tests/documents/sample_rss.xml" |
162 | | - ); |
163 | | - |
164 | | - #[cfg(not(windows))] |
165 | | - assert_eq!( |
166 | | - nbtxt, 50261, |
167 | | - "Overall length (in bytes) of all text contents of ./tests/documents/sample_rss.xml" |
168 | | - ); |
169 | | - }); |
170 | | - }); |
171 | | - group.finish(); |
172 | | -} |
173 | | - |
174 | | -/// Benchmarks, how fast individual event parsed |
175 | | -fn one_event(c: &mut Criterion) { |
176 | | - let mut group = c.benchmark_group("One event"); |
177 | | - group.bench_function("StartText", |b| { |
178 | | - let src = "Hello world!".repeat(512 / 12).into_bytes(); |
179 | | - let mut buf = Vec::with_capacity(1024); |
180 | | - b.iter(|| { |
181 | | - let mut r = Reader::from_reader(src.as_ref()); |
182 | | - let mut nbtxt = criterion::black_box(0); |
183 | | - r.check_end_names(false).check_comments(false); |
184 | | - match r.read_event(&mut buf) { |
185 | | - Ok(Event::StartText(e)) => nbtxt += e.len(), |
186 | | - something_else => panic!("Did not expect {:?}", something_else), |
187 | | - }; |
188 | | - |
189 | | - buf.clear(); |
190 | | - |
191 | | - assert_eq!(nbtxt, 504); |
192 | | - }) |
193 | | - }); |
194 | | - |
195 | | - group.bench_function("Start", |b| { |
196 | | - let src = format!(r#"<hello target="{}">"#, "world".repeat(512 / 5)).into_bytes(); |
197 | | - let mut buf = Vec::with_capacity(1024); |
198 | | - b.iter(|| { |
199 | | - let mut r = Reader::from_reader(src.as_ref()); |
200 | | - let mut nbtxt = criterion::black_box(0); |
201 | | - r.check_end_names(false) |
202 | | - .check_comments(false) |
203 | | - .trim_text(true); |
204 | | - match r.read_event(&mut buf) { |
205 | | - Ok(Event::Start(ref e)) => nbtxt += e.len(), |
206 | | - something_else => panic!("Did not expect {:?}", something_else), |
207 | | - }; |
208 | | - |
209 | | - buf.clear(); |
210 | | - |
211 | | - assert_eq!(nbtxt, 525); |
212 | | - }) |
213 | | - }); |
214 | | - |
215 | | - group.bench_function("Comment", |b| { |
216 | | - let src = format!(r#"<!-- hello "{}" -->"#, "world".repeat(512 / 5)).into_bytes(); |
217 | | - let mut buf = Vec::with_capacity(1024); |
218 | | - b.iter(|| { |
219 | | - let mut r = Reader::from_reader(src.as_ref()); |
220 | | - let mut nbtxt = criterion::black_box(0); |
221 | | - r.check_end_names(false) |
222 | | - .check_comments(false) |
223 | | - .trim_text(true); |
224 | | - match r.read_event(&mut buf) { |
225 | | - Ok(Event::Comment(ref e)) => nbtxt += e.unescaped().unwrap().len(), |
226 | | - something_else => panic!("Did not expect {:?}", something_else), |
227 | | - }; |
228 | | - |
229 | | - buf.clear(); |
230 | | - |
231 | | - assert_eq!(nbtxt, 520); |
232 | | - }) |
233 | | - }); |
234 | | - |
235 | | - group.bench_function("CData", |b| { |
236 | | - let src = format!(r#"<![CDATA[hello "{}"]]>"#, "world".repeat(512 / 5)).into_bytes(); |
237 | | - let mut buf = Vec::with_capacity(1024); |
238 | | - b.iter(|| { |
239 | | - let mut r = Reader::from_reader(src.as_ref()); |
240 | | - let mut nbtxt = criterion::black_box(0); |
241 | | - r.check_end_names(false) |
242 | | - .check_comments(false) |
243 | | - .trim_text(true); |
244 | | - match r.read_event(&mut buf) { |
245 | | - Ok(Event::CData(ref e)) => nbtxt += e.len(), |
246 | | - something_else => panic!("Did not expect {:?}", something_else), |
247 | | - }; |
248 | | - |
249 | | - buf.clear(); |
250 | | - |
251 | | - assert_eq!(nbtxt, 518); |
252 | | - }) |
253 | | - }); |
254 | | - group.finish(); |
255 | | -} |
256 | | - |
257 | | -/// Benchmarks parsing attributes from events |
258 | | -fn attributes(c: &mut Criterion) { |
259 | | - let mut group = c.benchmark_group("attributes"); |
260 | | - group.bench_function("with_checks = true", |b| { |
261 | | - b.iter(|| { |
262 | | - let mut r = Reader::from_reader(PLAYERS); |
263 | | - r.check_end_names(false).check_comments(false); |
264 | | - let mut count = criterion::black_box(0); |
265 | | - let mut buf = Vec::new(); |
266 | | - loop { |
267 | | - match r.read_event(&mut buf) { |
268 | | - Ok(Event::Empty(e)) => { |
269 | | - for attr in e.attributes() { |
270 | | - let _attr = attr.unwrap(); |
271 | | - count += 1 |
272 | | - } |
273 | | - } |
274 | | - Ok(Event::Eof) => break, |
275 | | - _ => (), |
276 | | - } |
277 | | - buf.clear(); |
278 | | - } |
279 | | - assert_eq!(count, 1041); |
280 | | - }) |
281 | | - }); |
282 | | - |
283 | | - group.bench_function("with_checks = false", |b| { |
284 | | - b.iter(|| { |
285 | | - let mut r = Reader::from_reader(PLAYERS); |
286 | | - r.check_end_names(false).check_comments(false); |
287 | | - let mut count = criterion::black_box(0); |
288 | | - let mut buf = Vec::new(); |
289 | | - loop { |
290 | | - match r.read_event(&mut buf) { |
291 | | - Ok(Event::Empty(e)) => { |
292 | | - for attr in e.attributes().with_checks(false) { |
293 | | - let _attr = attr.unwrap(); |
294 | | - count += 1 |
295 | | - } |
296 | | - } |
297 | | - Ok(Event::Eof) => break, |
298 | | - _ => (), |
299 | | - } |
300 | | - buf.clear(); |
301 | | - } |
302 | | - assert_eq!(count, 1041); |
303 | | - }) |
304 | | - }); |
305 | | - |
306 | | - group.bench_function("try_get_attribute", |b| { |
307 | | - b.iter(|| { |
308 | | - let mut r = Reader::from_reader(PLAYERS); |
309 | | - r.check_end_names(false).check_comments(false); |
310 | | - let mut count = criterion::black_box(0); |
311 | | - let mut buf = Vec::new(); |
312 | | - loop { |
313 | | - match r.read_event(&mut buf) { |
314 | | - Ok(Event::Empty(e)) if e.name() == QName(b"player") => { |
315 | | - for name in ["num", "status", "avg"] { |
316 | | - if let Some(_attr) = e.try_get_attribute(name).unwrap() { |
317 | | - count += 1 |
318 | | - } |
319 | | - } |
320 | | - assert!(e |
321 | | - .try_get_attribute("attribute-that-doesn't-exist") |
322 | | - .unwrap() |
323 | | - .is_none()); |
324 | | - } |
325 | | - Ok(Event::Eof) => break, |
326 | | - _ => (), |
327 | | - } |
328 | | - buf.clear(); |
329 | | - } |
330 | | - assert_eq!(count, 150); |
331 | | - }) |
332 | | - }); |
333 | | - group.finish(); |
334 | | -} |
335 | | - |
336 | | -criterion_group!( |
337 | | - benches, |
338 | | - read_event, |
339 | | - bytes_text_unescaped, |
340 | | - read_namespaced_event, |
341 | | - one_event, |
342 | | - attributes |
343 | | -); |
344 | | -criterion_main!(benches); |
| 6 | +criterion_main!(macrobenches::benches, microbenches::benches); |
0 commit comments