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