Add benchmark

This commit is contained in:
Simon Ask Ulsnes 2024-02-04 15:16:58 +01:00
parent f096658622
commit 047bb8dfcb
3 changed files with 38233 additions and 1 deletions

View file

@ -11,9 +11,10 @@ license-file = "LICENSE-MIT"
repository = "https://github.com/simonask/libyaml-safer" repository = "https://github.com/simonask/libyaml-safer"
rust-version = "1.70" rust-version = "1.70"
[workspace]
[dev-dependencies] [dev-dependencies]
criterion = "0.5.1"
pretty_assertions = "1.0" pretty_assertions = "1.0"
unsafe-libyaml = "0.2.10"
unsafe-libyaml-test-suite = { path = "tests/data" } unsafe-libyaml-test-suite = { path = "tests/data" }
[lib] [lib]
@ -25,3 +26,7 @@ thiserror = "1.0"
[package.metadata.docs.rs] [package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"] targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = ["--generate-link-to-definition"] rustdoc-args = ["--generate-link-to-definition"]
[[bench]]
name = "bench"
harness = false

122
benches/bench.rs Normal file
View file

@ -0,0 +1,122 @@
use std::mem::MaybeUninit;
use criterion::{criterion_group, criterion_main, Criterion};
use libyaml_safer::{Document, Emitter, Parser};
use unsafe_libyaml::*;
static VERY_LARGE_YAML: &[u8] = include_bytes!("very_large.yml");
pub fn parser(c: &mut Criterion) {
c.bench_function("libyaml-safer parse large", |b| {
// Note: Not using `iter_with_large_drop` because that would be unfair
// to unsafe-libyaml, which needs a call to `yaml_document_delete`.
b.iter(|| {
let mut input = VERY_LARGE_YAML;
let mut parser = Parser::new();
parser.set_input(&mut input);
Document::load(&mut parser)
})
});
c.bench_function("unsafe-libyaml parse large", |b| {
b.iter(|| unsafe {
let mut parser = MaybeUninit::zeroed();
if !yaml_parser_initialize(parser.as_mut_ptr()).ok {
panic!("yaml_parser_initialize failed");
}
let mut parser = parser.assume_init();
yaml_parser_set_input_string(
&mut parser,
VERY_LARGE_YAML.as_ptr(),
VERY_LARGE_YAML.len() as _,
);
let mut document = MaybeUninit::zeroed();
if !yaml_parser_load(&mut parser, document.as_mut_ptr()).ok {
panic!("yaml_parser_load faled");
};
yaml_document_delete(document.as_mut_ptr());
yaml_parser_delete(&mut parser);
})
});
c.bench_function("libyaml-safer emit large", |b| {
// output shouldn't be much larger than the input, but just to be safe...
let mut buffer = Vec::with_capacity(VERY_LARGE_YAML.len());
let doc = {
let mut parser = Parser::new();
let mut input = VERY_LARGE_YAML;
parser.set_input(&mut input);
Document::load(&mut parser).unwrap()
};
b.iter_custom(|iters| {
let mut measurement = std::time::Duration::ZERO;
for _ in 0..iters {
let doc = doc.clone();
let start_time = std::time::Instant::now();
let mut emitter = Emitter::new();
emitter.set_output(&mut buffer);
doc.dump(&mut emitter).unwrap();
measurement += start_time.elapsed();
}
measurement
});
});
c.bench_function("unsafe-libyaml emit large", |b| {
// output shouldn't be much larger than the input, but just to be safe...
let mut buffer = vec![0; VERY_LARGE_YAML.len() * 2];
// `yaml_document_t` cannot be cloned, so we have to parse it every iteration unfortunately.
let read_doc = || unsafe {
let mut parser = MaybeUninit::zeroed();
if !yaml_parser_initialize(parser.as_mut_ptr()).ok {
panic!("yaml_parser_initialize failed");
}
let mut parser = parser.assume_init();
yaml_parser_set_input_string(
&mut parser,
VERY_LARGE_YAML.as_ptr(),
VERY_LARGE_YAML.len() as _,
);
let mut document = MaybeUninit::zeroed();
if !yaml_parser_load(&mut parser, document.as_mut_ptr()).ok {
panic!("yaml_parser_load faled");
};
yaml_parser_delete(&mut parser);
document.assume_init()
};
b.iter_custom(|iters| {
let mut measurement = std::time::Duration::ZERO;
for _ in 0..iters {
unsafe {
let mut doc = read_doc();
let start_time = std::time::Instant::now();
let mut emitter = MaybeUninit::zeroed();
if !yaml_emitter_initialize(emitter.as_mut_ptr()).ok {
panic!("yaml_emitter_initialize failed");
}
let mut emitter = emitter.assume_init();
let mut size_written = 0;
yaml_emitter_set_output_string(
&mut emitter,
buffer.as_mut_ptr(),
buffer.len() as _,
&mut size_written,
);
if !yaml_emitter_dump(&mut emitter, &mut doc).ok {
panic!("yaml_emitter_dump failed");
}
measurement += start_time.elapsed();
yaml_emitter_delete(&mut emitter);
}
}
measurement
});
});
}
criterion_group!(benches, parser);
criterion_main!(benches);

38105
benches/very_large.yml Normal file

File diff suppressed because it is too large Load diff