1 use criterion::black_box;
2
3 use winnow::combinator::opt;
4 use winnow::prelude::*;
5 use winnow::stream::AsChar;
6 use winnow::stream::Stream as _;
7 use winnow::token::one_of;
8
iter(c: &mut criterion::Criterion)9 fn iter(c: &mut criterion::Criterion) {
10 let data = [
11 ("contiguous", CONTIGUOUS.as_bytes()),
12 ("interleaved", INTERLEAVED.as_bytes()),
13 ("canada", CANADA.as_bytes()),
14 ];
15 let mut group = c.benchmark_group("iter");
16 for (name, sample) in data {
17 let len = sample.len();
18 group.throughput(criterion::Throughput::Bytes(len as u64));
19
20 group.bench_with_input(
21 criterion::BenchmarkId::new("iterate", name),
22 &len,
23 |b, _| {
24 b.iter(|| black_box(iterate.parse_peek(black_box(sample)).unwrap()));
25 },
26 );
27 group.bench_with_input(
28 criterion::BenchmarkId::new("next_token", name),
29 &len,
30 |b, _| {
31 b.iter(|| black_box(next_token.parse_peek(black_box(sample)).unwrap()));
32 },
33 );
34 group.bench_with_input(
35 criterion::BenchmarkId::new("opt(one_of)", name),
36 &len,
37 |b, _| {
38 b.iter(|| black_box(opt_one_of.parse_peek(black_box(sample)).unwrap()));
39 },
40 );
41 group.bench_with_input(
42 criterion::BenchmarkId::new("take_while", name),
43 &len,
44 |b, _| {
45 b.iter(|| black_box(take_while.parse_peek(black_box(sample)).unwrap()));
46 },
47 );
48 group.bench_with_input(criterion::BenchmarkId::new("repeat", name), &len, |b, _| {
49 b.iter(|| black_box(repeat.parse_peek(black_box(sample)).unwrap()));
50 });
51 }
52 group.finish();
53 }
54
iterate(input: &mut &[u8]) -> PResult<usize>55 fn iterate(input: &mut &[u8]) -> PResult<usize> {
56 let mut count = 0;
57 for byte in input.iter() {
58 if byte.is_dec_digit() {
59 count += 1;
60 }
61 }
62 input.finish();
63 Ok(count)
64 }
65
next_token(input: &mut &[u8]) -> PResult<usize>66 fn next_token(input: &mut &[u8]) -> PResult<usize> {
67 let mut count = 0;
68 while let Some(byte) = input.next_token() {
69 if byte.is_dec_digit() {
70 count += 1;
71 }
72 }
73 Ok(count)
74 }
75
opt_one_of(input: &mut &[u8]) -> PResult<usize>76 fn opt_one_of(input: &mut &[u8]) -> PResult<usize> {
77 let mut count = 0;
78 while !input.is_empty() {
79 while opt(one_of(AsChar::is_dec_digit))
80 .parse_next(input)?
81 .is_some()
82 {
83 count += 1;
84 }
85 while opt(one_of(|b: u8| !b.is_dec_digit()))
86 .parse_next(input)?
87 .is_some()
88 {}
89 }
90 Ok(count)
91 }
92
take_while(input: &mut &[u8]) -> PResult<usize>93 fn take_while(input: &mut &[u8]) -> PResult<usize> {
94 let mut count = 0;
95 while !input.is_empty() {
96 count += winnow::token::take_while(0.., AsChar::is_dec_digit)
97 .parse_next(input)?
98 .len();
99 let _ = winnow::token::take_while(0.., |b: u8| !b.is_dec_digit()).parse_next(input)?;
100 }
101 Ok(count)
102 }
103
repeat(input: &mut &[u8]) -> PResult<usize>104 fn repeat(input: &mut &[u8]) -> PResult<usize> {
105 let mut count = 0;
106 while !input.is_empty() {
107 count += winnow::combinator::repeat(0.., one_of(AsChar::is_dec_digit))
108 .map(|count: usize| count)
109 .parse_next(input)?;
110 winnow::combinator::repeat(0.., one_of(|b: u8| !b.is_dec_digit())).parse_next(input)?;
111 }
112 Ok(count)
113 }
114
115 const CONTIGUOUS: &str = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
116 const INTERLEAVED: &str = "0123456789abc0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab0123456789ab";
117 const CANADA: &str = include_str!("../third_party/nativejson-benchmark/data/canada.json");
118
119 criterion::criterion_group!(benches, iter);
120 criterion::criterion_main!(benches);
121