use criterion::{black_box, criterion_group, criterion_main, Criterion}; use nom_gcode::{DocComment, GCodeLine, Mnemonic, doc_comment, parse_gcode, parse_command, parse_args, ArgOrComment, parse_kv_arg}; fn criterion_benchmark(c: &mut Criterion) { let doc = ";Filament used: 0.943758m"; let mut group = c.benchmark_group("doc_comment"); group.bench_function("parse_gcode", |b| b.iter(|| { let gcode_line = parse_gcode(black_box(doc)) .unwrap() .1 .unwrap(); if let GCodeLine::DocComment(DocComment::FilamentUsed { meters}) = gcode_line { assert_eq!(meters, 0.943758); } else { panic!("Expected a doc comment"); } })); group.bench_function("doc_comment_only", |b| b.iter(|| { let gcode_line = doc_comment(black_box(doc)) .unwrap() .1; if let DocComment::FilamentUsed { meters} = gcode_line { assert_eq!(meters, 0.943758); } else { panic!("Expected a doc comment"); } })); group.finish(); let g1 = "G1 X132.273 Y137.397 E3.64358"; let g1_args = vec![ ('X', Some(132.273)), ('Y', Some(137.397)), ('E', Some(3.64358)), ]; c.bench_function("parse_g1", |b| b.iter(|| { let gcode_line = parse_gcode(black_box(g1)) .unwrap() .1 .unwrap(); if let GCodeLine::GCode(gcode) = gcode_line { assert_eq!(gcode.line_number, None); assert_eq!(gcode.mnemonic, Mnemonic::General); assert_eq!(gcode.major, 1); assert_eq!(gcode.minor, 0); let mut args = gcode.arguments(); assert_eq!(args.next(), g1_args.get(0)); assert_eq!(args.next(), g1_args.get(1)); assert_eq!(args.next(), g1_args.get(2)); assert_eq!(args.next(), None); } else { panic!("Expected a G1"); } })); c.bench_function("parse_command g1", |b| b.iter(|| { let (_, gcode) = parse_command(black_box(g1)) .unwrap(); assert_eq!(gcode.line_number, None); assert_eq!(gcode.mnemonic, Mnemonic::General); assert_eq!(gcode.major, 1); assert_eq!(gcode.minor, 0); // let mut args = gcode.arguments(); // assert_eq!(args.next(), g1_args.get(0)); // assert_eq!(args.next(), g1_args.get(1)); // assert_eq!(args.next(), g1_args.get(2)); // assert_eq!(args.next(), None); })); c.bench_function("parse_command parse_args g1", |b| b.iter(|| { let (input, gcode) = parse_command(black_box(g1)) .unwrap(); assert_eq!(gcode.line_number, None); assert_eq!(gcode.mnemonic, Mnemonic::General); assert_eq!(gcode.major, 1); assert_eq!(gcode.minor, 0); let (_, args) = parse_args(false, input).unwrap(); let mut args = args.unwrap() .into_iter() .filter_map(|arg| { if let ArgOrComment::KeyValue(key_value) = arg { Some(key_value) } else { None } }); assert_eq!(args.next().as_ref(), g1_args.get(0)); assert_eq!(args.next().as_ref(), g1_args.get(1)); assert_eq!(args.next().as_ref(), g1_args.get(2)); assert_eq!(args.next(), None); })); c.bench_function("parse_command parse_kv_arg loop g1", |b| b.iter(|| { let (mut input, gcode) = parse_command(black_box(g1)) .unwrap(); assert_eq!(gcode.line_number, None); assert_eq!(gcode.mnemonic, Mnemonic::General); assert_eq!(gcode.major, 1); assert_eq!(gcode.minor, 0); let mut arg_count = 0; loop { let arg = match parse_kv_arg(input) { Ok((rem, ArgOrComment::KeyValue(arg))) => { input = rem; Some(arg) } Ok(_) => continue, Err(_) => break, }; assert_eq!(arg.as_ref(), g1_args.get(arg_count)); arg_count += 1; } assert_eq!(arg_count, 3) })); } criterion_group!(benches, criterion_benchmark); criterion_main!(benches);