1#[global_allocator] 2static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; 3 4use criterion::*; 5 6use nom::{ 7 bytes::complete::take_while, 8 character::complete::{ 9 alphanumeric1 as alphanumeric, char, multispace1 as multispace, space1 as space, 10 }, 11 combinator::{map, map_res, opt}, 12 multi::many0, 13 sequence::{delimited, pair, separated_pair, terminated, tuple}, 14 IResult, 15}; 16use std::collections::HashMap; 17use std::str; 18 19fn category(i: &[u8]) -> IResult<&[u8], &str> { 20 map_res( 21 delimited(char('['), take_while(|c| c != b']'), char(']')), 22 str::from_utf8, 23 )(i) 24} 25 26fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> { 27 let (i, key) = map_res(alphanumeric, str::from_utf8)(i)?; 28 let (i, _) = tuple((opt(space), char('='), opt(space)))(i)?; 29 let (i, val) = map_res(take_while(|c| c != b'\n' && c != b';'), str::from_utf8)(i)?; 30 let (i, _) = opt(pair(char(';'), take_while(|c| c != b'\n')))(i)?; 31 Ok((i, (key, val))) 32} 33 34fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> { 35 map( 36 many0(separated_pair( 37 category, 38 opt(multispace), 39 map( 40 many0(terminated(key_value, opt(multispace))), 41 |vec: Vec<_>| vec.into_iter().collect(), 42 ), 43 )), 44 |vec: Vec<_>| vec.into_iter().collect(), 45 )(i) 46} 47 48fn bench_ini(c: &mut Criterion) { 49 let str = "[owner] 50name=John Doe 51organization=Acme Widgets Inc. 52 53[database] 54server=192.0.2.62 55port=143 56file=payroll.dat 57\0"; 58 59 let mut group = c.benchmark_group("ini"); 60 group.throughput(Throughput::Bytes(str.len() as u64)); 61 group.bench_function(BenchmarkId::new("parse", str.len()), |b| { 62 b.iter(|| categories(str.as_bytes()).unwrap()) 63 }); 64} 65 66fn bench_ini_keys_and_values(c: &mut Criterion) { 67 let str = "server=192.0.2.62 68port=143 69file=payroll.dat 70\0"; 71 72 fn acc(i: &[u8]) -> IResult<&[u8], Vec<(&str, &str)>> { 73 many0(key_value)(i) 74 } 75 76 let mut group = c.benchmark_group("ini keys and values"); 77 group.throughput(Throughput::Bytes(str.len() as u64)); 78 group.bench_function(BenchmarkId::new("parse", str.len()), |b| { 79 b.iter(|| acc(str.as_bytes()).unwrap()) 80 }); 81} 82 83fn bench_ini_key_value(c: &mut Criterion) { 84 let str = "server=192.0.2.62\n"; 85 86 let mut group = c.benchmark_group("ini key value"); 87 group.throughput(Throughput::Bytes(str.len() as u64)); 88 group.bench_function(BenchmarkId::new("parse", str.len()), |b| { 89 b.iter(|| key_value(str.as_bytes()).unwrap()) 90 }); 91} 92 93criterion_group!( 94 benches, 95 bench_ini, 96 bench_ini_keys_and_values, 97 bench_ini_key_value 98); 99criterion_main!(benches); 100