use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use typeset::*;
fn create_simple_layout() -> Box<Layout> {
join_with_spaces(vec![
text_str("Hello"),
text_str("World"),
text_str("from"),
text_str("typeset"),
])
}
fn create_nested_layout(depth: usize) -> Box<Layout> {
let mut layout = text_str("base");
for i in 0..depth {
layout = nest(comp(text_str(&format!("level_{}", i)), layout, true, false));
}
layout
}
fn create_wide_layout(width: usize) -> Box<Layout> {
let items: Vec<_> = (0..width)
.map(|i| text_str(&format!("item_{}", i)))
.collect();
join_with_spaces(items)
}
fn create_json_like_layout(size: usize) -> Box<Layout> {
let entries: Vec<_> = (0..size)
.map(|i| {
unpad(
unpad(text_str(&format!("\"key_{}\"", i)), text_str(": ")),
text_str(&format!("\"value_{}\"", i)),
)
})
.collect();
braces(nest(join_with_lines(
vec![null()]
.into_iter()
.chain(entries.into_iter().enumerate().map(|(i, entry)| {
if i == 0 {
entry
} else {
unpad(comma(), pad(null(), entry))
}
}))
.chain(vec![null()])
.collect(),
)))
}
fn bench_construction(c: &mut Criterion) {
let mut group = c.benchmark_group("construction");
group.bench_function("simple", |b| b.iter(create_simple_layout));
for depth in [5, 10, 20].iter() {
group.bench_with_input(BenchmarkId::new("nested", depth), depth, |b, &depth| {
b.iter(|| create_nested_layout(depth))
});
}
for width in [10, 50, 100].iter() {
group.bench_with_input(BenchmarkId::new("wide", width), width, |b, &width| {
b.iter(|| create_wide_layout(width))
});
}
for size in [5, 10, 25].iter() {
group.bench_with_input(BenchmarkId::new("json_like", size), size, |b, &size| {
b.iter(|| create_json_like_layout(size))
});
}
group.finish();
}
fn bench_compilation(c: &mut Criterion) {
let mut group = c.benchmark_group("compilation");
let simple = create_simple_layout();
group.bench_function("simple", |b| b.iter(|| compile(simple.clone())));
for depth in [5, 10, 20].iter() {
let layout = create_nested_layout(*depth);
group.bench_with_input(BenchmarkId::new("nested", depth), depth, |b, _| {
b.iter(|| compile(layout.clone()))
});
}
for width in [10, 50, 100].iter() {
let layout = create_wide_layout(*width);
group.bench_with_input(BenchmarkId::new("wide", width), width, |b, _| {
b.iter(|| compile(layout.clone()))
});
}
for size in [5, 10, 25].iter() {
let layout = create_json_like_layout(*size);
group.bench_with_input(BenchmarkId::new("json_like", size), size, |b, _| {
b.iter(|| compile(layout.clone()))
});
}
group.finish();
}
fn bench_rendering(c: &mut Criterion) {
let mut group = c.benchmark_group("rendering");
let simple_doc = compile(create_simple_layout());
group.bench_function("simple", |b| b.iter(|| render(simple_doc.clone(), 2, 80)));
let complex_doc = compile(create_json_like_layout(20));
for width in [20, 40, 80, 120].iter() {
group.bench_with_input(
BenchmarkId::new("different_widths", width),
width,
|b, &width| b.iter(|| render(complex_doc.clone(), 2, width)),
);
}
group.finish();
}
fn bench_end_to_end(c: &mut Criterion) {
let mut group = c.benchmark_group("end_to_end");
group.bench_function("simple", |b| {
b.iter(|| {
let layout = create_simple_layout();
let doc = compile(layout);
render(doc, 2, 80)
})
});
for size in [5, 10, 20].iter() {
group.bench_with_input(BenchmarkId::new("json_like", size), size, |b, &size| {
b.iter(|| {
let layout = create_json_like_layout(size);
let doc = compile(layout);
render(doc, 2, 80)
})
});
}
group.bench_function("convenience_api", |b| {
b.iter(|| {
let layout = create_simple_layout();
format_layout(layout, 2, 80)
})
});
group.finish();
}
fn bench_reuse_efficiency(c: &mut Criterion) {
let mut group = c.benchmark_group("reuse_efficiency");
let doc = compile(create_json_like_layout(15));
group.bench_function("compile_once_render_multiple", |b| {
b.iter(|| {
for width in [20, 40, 60, 80, 100] {
let _ = render(doc.clone(), 2, width);
}
})
});
group.bench_function("compile_each_time", |b| {
b.iter(|| {
let layout = create_json_like_layout(15);
for width in [20, 40, 60, 80, 100] {
let doc = compile(layout.clone());
let _ = render(doc, 2, width);
}
})
});
group.finish();
}
fn bench_combinators(c: &mut Criterion) {
let mut group = c.benchmark_group("combinators");
let base = text_str("content");
group.bench_function("text", |b| b.iter(|| text_str("benchmark text")));
group.bench_function("comp_padded", |b| {
b.iter(|| comp(base.clone(), base.clone(), true, false))
});
group.bench_function("comp_unpadded", |b| {
b.iter(|| comp(base.clone(), base.clone(), false, false))
});
group.bench_function("line", |b| b.iter(|| line(base.clone(), base.clone())));
group.bench_function("nest", |b| b.iter(|| nest(base.clone())));
group.bench_function("pack", |b| b.iter(|| pack(base.clone())));
group.bench_function("fix", |b| b.iter(|| fix(base.clone())));
group.bench_function("grp", |b| b.iter(|| grp(base.clone())));
group.bench_function("seq", |b| b.iter(|| seq(base.clone())));
group.finish();
}
criterion_group!(
benches,
bench_construction,
bench_compilation,
bench_rendering,
bench_end_to_end,
bench_reuse_efficiency,
bench_combinators
);
criterion_main!(benches);