From 83e0748b9ec6a6f0c848cdff41bab1a77a9f618a Mon Sep 17 00:00:00 2001 From: Huck Boles Date: Sun, 14 May 2023 14:43:08 -0500 Subject: [PATCH] better benchmarks --- benches/build_site.rs | 24 +++++++++----- benches/map_dir.rs | 27 ++++++++++++++++ files/site/pattern/body/bench.meta | 6 ++++ files/site/pattern/footer/bench.meta | 1 + files/site/pattern/header/bench.meta | 11 +++++++ files/site/pattern/list/item/bench.meta | 1 + files/site/source/benchmark.meta | 43 +++++++++++++++++++++++++ src/builder.rs | 15 ++++----- src/lib.rs | 32 ++++++++++++++++++ src/main.rs | 23 ++----------- src/metafile.rs | 15 ++++++--- src/parser.rs | 8 ++++- 12 files changed, 164 insertions(+), 42 deletions(-) create mode 100644 benches/map_dir.rs create mode 100644 files/site/pattern/body/bench.meta create mode 100644 files/site/pattern/footer/bench.meta create mode 100644 files/site/pattern/header/bench.meta create mode 100644 files/site/pattern/list/item/bench.meta create mode 100644 files/site/source/benchmark.meta diff --git a/benches/build_site.rs b/benches/build_site.rs index 07e4ca1..96304d2 100644 --- a/benches/build_site.rs +++ b/benches/build_site.rs @@ -1,23 +1,31 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use metaforge::Options; -pub fn build_site_benchmark(c: &mut Criterion) { +pub fn build_file_benchmark(c: &mut Criterion) { let dir = std::path::PathBuf::from("files/site") .canonicalize() .unwrap(); - let mut opts = Options::new(); + let mut opts = metaforge::Options::new(); opts.root = dir.clone(); opts.source = dir.join("source"); opts.build = dir.join("build"); opts.pattern = dir.join("pattern"); opts.clean = true; - todo!("implement with DirNode") - // c.bench_function("build test site", |b| { - // b.iter(|| build_site(black_box(&opts))) - // }); + let source = opts.source.join("benchmark.meta"); + + c.bench_function("build benchmark file", |b| { + b.iter(|| { + let string = std::fs::read_to_string(black_box(&source)).unwrap(); + let file = metaforge::parse_file(string, black_box(&opts)).unwrap(); + let mut path = opts + .build + .join(source.strip_prefix(black_box(&opts.source)).unwrap()); + path.set_extension("html"); + std::fs::write(path, metaforge::build_metafile(&file).unwrap()).unwrap(); + }) + }); } -criterion_group!(benches, build_site_benchmark); +criterion_group!(benches, build_file_benchmark); criterion_main!(benches); diff --git a/benches/map_dir.rs b/benches/map_dir.rs new file mode 100644 index 0000000..c1434f7 --- /dev/null +++ b/benches/map_dir.rs @@ -0,0 +1,27 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +pub fn map_dir_benchmark(c: &mut Criterion) { + let dir = std::path::PathBuf::from("files/site") + .canonicalize() + .unwrap(); + + let mut opts = metaforge::Options::new(); + opts.root = dir.clone(); + opts.source = dir.join("source"); + opts.build = dir.join("build"); + opts.pattern = dir.join("pattern"); + opts.clean = true; + + c.bench_function("build benchmark file", |b| { + b.iter(|| { + let mut dir = + metaforge::DirNode::build(black_box(opts.source.clone()), black_box(&opts)) + .unwrap(); + let tmp = metaforge::MetaFile::new(black_box(&opts)); + dir.map(&tmp).unwrap(); + }) + }); +} + +criterion_group!(benches, map_dir_benchmark); +criterion_main!(benches); diff --git a/files/site/pattern/body/bench.meta b/files/site/pattern/body/bench.meta new file mode 100644 index 0000000..8c1e1fa --- /dev/null +++ b/files/site/pattern/body/bench.meta @@ -0,0 +1,6 @@ + + &{header} + ${bench_variable} + &{SOURCE} + &{footer} + diff --git a/files/site/pattern/footer/bench.meta b/files/site/pattern/footer/bench.meta new file mode 100644 index 0000000..c8f73d7 --- /dev/null +++ b/files/site/pattern/footer/bench.meta @@ -0,0 +1 @@ +@{array} diff --git a/files/site/pattern/header/bench.meta b/files/site/pattern/header/bench.meta new file mode 100644 index 0000000..80351bf --- /dev/null +++ b/files/site/pattern/header/bench.meta @@ -0,0 +1,11 @@ +@{ + link.url = ['a.com','a.com','a.com','a.com','a.com','a.com','a.com','a.com','a.com','a.com'] + link.title = ['a','a','a','a','a','a','a','a','a','a'] +} + +&{ + list.item = 'bench' +} + +&{list} + diff --git a/files/site/pattern/list/item/bench.meta b/files/site/pattern/list/item/bench.meta new file mode 100644 index 0000000..b4259e0 --- /dev/null +++ b/files/site/pattern/list/item/bench.meta @@ -0,0 +1 @@ +
  • &{link}
  • diff --git a/files/site/source/benchmark.meta b/files/site/source/benchmark.meta new file mode 100644 index 0000000..68eec32 --- /dev/null +++ b/files/site/source/benchmark.meta @@ -0,0 +1,43 @@ +#{ filetype = 'html' } + +${ + var = 'variables' + inline = 'inline variables' + bench_variable = 'this is a really long variable that contains multiple lines + and other interesting features to test how well metaforge deals long variables + \t this is a list: + - to + - see + - how + - flexible + - variables + - are + pretty cool!' + +} + +@{ + single = ['single value arrays'] + footer.array = ['1','2','3','4','5','6','7','8','9','10'] +} + +&{ + body = 'bench' + header = 'bench' + footer = 'bench' +} + +# THIS IS THE BENCHMARK FILE FOR METAFORGE + +*it has __${var}* and @{single}__ + +

    Some inline html with ${inline}

    + +-{comments before a line} ### Other Tests + +a bunch of symbols !@#$%^&*())_ + +code blocks: +``` +let f = "foo" +``` diff --git a/src/builder.rs b/src/builder.rs index b1b757a..08deae6 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -10,10 +10,10 @@ use std::{ pub fn build_metafile(file: &MetaFile) -> Result { let html = get_source_html(file, file.opts)?; - let pattern = get_pattern("base", &file)?; + let pattern = get_pattern("base", file)?; let mut base = parse_file(pattern, file.opts)?; - base.merge(&file); + base.merge(file); base.patterns.insert("SOURCE".to_string(), html); let output = metafile_to_string(&base)?; @@ -24,7 +24,7 @@ pub fn build_metafile(file: &MetaFile) -> Result { pub fn write_file(path: &Path, html: String, opts: &Options) -> Result<()> { let dest = find_dest(path, opts)?; // want newline to end file - fs::write(&dest, html + "\n")?; + fs::write(dest, html + "\n")?; Ok(()) } @@ -135,21 +135,19 @@ fn get_pattern(key: &str, file: &MetaFile) -> Result { let mut pattern = MetaFile::build(path, file.opts)?; // copy over maps for expanding contained variables - pattern.merge(&file); + pattern.merge(file); metafile_to_string(&pattern) } -fn get_variable(key: &str, file: &MetaFile) -> Result { +fn get_variable(_key: &str, _file: &MetaFile) -> Result { todo!() } fn find_dest(path: &Path, opts: &Options) -> Result { let path = path.canonicalize()?; - let path = opts.build.join(path.strip_prefix(&opts.source)?); - let mut path = PathBuf::from(path); - + let mut path = opts.build.join(path.strip_prefix(&opts.source)?); path.set_extension("html"); Ok(path) @@ -169,7 +167,6 @@ fn expand_arrays(input: String, file: &MetaFile) -> Result { }) // make a hash map of [keys in source] -> [defined arrays] .map(|key| { - let y: String; // concat array to pattern name to get key in HashMap let name = file.name().unwrap(); let long_key = name + "." + key; diff --git a/src/lib.rs b/src/lib.rs index 3bb3fa3..9a9a080 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,3 +11,35 @@ pub use builder::*; pub use metafile::*; pub use options::*; pub use parser::*; + +use clap::Parser; +use color_eyre::Result; + +pub fn get_opts() -> Result { + let opts = Options::try_from(Opts::parse())?; + + log!( + opts, + format!("cleaning build directory: {}", opts.build.display()), + 1 + ); + if opts.clean && opts.build.exists() { + std::fs::remove_dir_all(&opts.build)?; + } + + if !opts.build.exists() { + std::fs::create_dir(&opts.build)?; + } + + Ok(opts) +} + +pub fn build_dir(opts: &Options) -> Result<()> { + let mut source = DirNode::build(opts.source.clone(), opts)?; + + let global_init = MetaFile::new(&opts); + + source.map(&global_init)?; + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index a23cfdf..6304640 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,7 @@ -use clap::Parser; -use color_eyre::Result; -use metaforge::{log, Options, Opts}; - -fn main() -> Result<()> { +fn main() -> color_eyre::Result<()> { color_eyre::install()?; - let opts = Options::try_from(Opts::parse())?; - - log!( - opts, - format!("cleaning build directory: {}", opts.build.display()), - 1 - ); - if opts.clean && opts.build.exists() { - std::fs::remove_dir_all(&opts.build)?; - } - - if !opts.build.exists() { - std::fs::create_dir(&opts.build)?; - } + let opts = metaforge::get_opts()?; - todo!("implement DirNode chain") + metaforge::build_dir(&opts) } diff --git a/src/metafile.rs b/src/metafile.rs index 8a76317..01ef06f 100644 --- a/src/metafile.rs +++ b/src/metafile.rs @@ -18,7 +18,7 @@ impl<'a> MetaFile<'a> { pub fn build(path: PathBuf, opts: &'a Options) -> Result { let str = fs::read_to_string(&path)?; let mut metafile = parse_file(str, opts)?; - metafile.path = path.to_path_buf(); + metafile.path = path; metafile.opts = opts; Ok(metafile) } @@ -37,12 +37,19 @@ impl<'a> MetaFile<'a> { pub fn name(&self) -> Result { if self.path.starts_with(&self.opts.source) { + // in source dir, we want the file name let name = self.path.strip_prefix(&self.opts.source)?; let name = name.to_string_lossy().to_string().replace('/', "."); Ok(name) } else { + // in pattern dir, we want the parent dir let name = self.path.strip_prefix(&self.opts.pattern)?; - let name = name.to_string_lossy().to_string().replace('/', "."); + let name = name + .parent() + .unwrap() + .to_string_lossy() + .to_string() + .replace('/', "."); Ok(name) } } @@ -121,7 +128,7 @@ impl<'a> DirNode<'a> { let global = MetaFile::new(opts); Ok(Self { - path: path.to_path_buf(), + path, opts, global, files, @@ -132,7 +139,7 @@ impl<'a> DirNode<'a> { // parses all contained files and directories and pushes // parsed structures into the files and directories vectors pub fn map(&mut self, global: &'a MetaFile) -> Result<()> { - for f in fs::read_dir(&self.path)?.into_iter() { + for f in fs::read_dir(&self.path)? { let file = f?.path(); if file.is_dir() { diff --git a/src/parser.rs b/src/parser.rs index 1eab219..65e11d3 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -10,7 +10,7 @@ use std::collections::HashMap; #[grammar = "meta.pest"] pub struct MetaParser; -pub fn parse_file<'a>(file: String, opts: &'a Options) -> Result> { +pub fn parse_file(file: String, opts: &Options) -> Result { let meta_source = MetaParser::parse(Rule::file, &file) .wrap_err("parser error")? .next() @@ -226,4 +226,10 @@ mod tests { fn map_source_map() { test_str!(r#"${var='v'} Some text @{array = ['a']}"#); } + + #[test] + #[should_panic] + fn header_not_first() { + test_str!(r#"${v='v'} #{ type = 'html'} @{a=['a']}"#); + } } -- 2.44.2