libyaml-safer/benches/bench.rs
Simon Ask Ulsnes 047bb8dfcb Add benchmark
2024-02-04 15:16:58 +01:00

122 lines
4.6 KiB
Rust

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);