use criterion::{ criterion_group, criterion_main, BenchmarkId, Criterion, Throughput, }; use markedit::{Heading, Matcher, Rewriter, Writer}; use pulldown_cmark::Event; use std::path::{Path, PathBuf}; fn known_markdown_files() -> impl Iterator { let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let markedit_files = vec![ manifest_dir.join("README.md"), manifest_dir.join("LICENSE_APACHE.md"), ]; let blog_posts_pattern = concat!( env!("CARGO_MANIFEST_DIR"), "/benches/adventures.michaelfbryan.com/content/posts/**/*.md" ); let blog_posts = glob::glob(blog_posts_pattern) .unwrap() .map(|entry| entry.unwrap()); blog_posts.chain(markedit_files) } fn canonical_name(path: &Path) -> &str { let stem = path.file_stem().unwrap().to_str().unwrap(); if stem == "index" { canonical_name(path.parent().unwrap()) } else { stem } } pub fn rewriting(c: &mut Criterion) { let mut group = c.benchmark_group("Rewriting"); for filename in known_markdown_files() { let src = std::fs::read_to_string(&filename).unwrap(); let name = canonical_name(&filename); group .throughput(Throughput::Bytes(src.len() as u64)) .bench_with_input( BenchmarkId::new("baseline parse", name), &src, |b, src| b.iter(|| markedit::parse(src).count()), ) .bench_with_input( BenchmarkId::new("add text after each heading", name), &src, |b, src| { b.iter(|| { markedit::insert_markdown_before( "## Sub-Heading", Heading::with_level(2).falling_edge(), ) .rewrite(markedit::parse(src)) .count() }) }, ) .bench_with_input( BenchmarkId::new("lowercase all text", name), &src, |b, src| { b.iter(|| { markedit::change_text( |_| true, |text| text.to_uppercase(), ) .rewrite(markedit::parse(src)) .count() }) }, ) .bench_with_input( BenchmarkId::new("uppercase level 2 headings", name), &src, |b, src| { b.iter(|| { upper_case_header_text(2) .rewrite(markedit::parse(src)) .count() }) }, ); } } fn upper_case_header_text<'src>(level: u32) -> impl Rewriter<'src> { let mut matcher = Heading::with_level(level); move |ev: Event<'src>, writer: &mut Writer<'src>| { if matcher.matches_event(&ev) { if let Event::Text(text) = ev { writer.push(Event::Text( text.into_string().to_uppercase().into(), )); return; } } writer.push(ev); } } criterion_group!(benches, rewriting); criterion_main!(benches);