use bench_utils::{bench, LARGE_XML, MEDIUM_XML, TINY_XML};
use criterion::{criterion_group, criterion_main, Criterion};
use std::fs::File;
use std::path::Path;
mod bench_utils;
mod xml_rs_bench {
use super::*;
use std::io::BufReader;
use xml_rs::reader::{EventReader, XmlEvent};
pub fn xml_rs_parser(path: &Path) -> usize {
let mut counter = 0;
let file = File::open(path).unwrap();
let file = BufReader::new(file);
let parser = EventReader::new(file);
for e in parser.into_iter().flatten() {
if let XmlEvent::StartElement {
name, attributes, ..
} = e
{
counter += name.local_name.len();
for attr in attributes {
counter += attr.value.len();
}
}
}
counter
}
}
use xml_rs_bench::xml_rs_parser;
bench!(TINY_XML, tiny_xml_rs, xml_rs_parser);
bench!(MEDIUM_XML, medium_xml_rs, xml_rs_parser);
bench!(LARGE_XML, large_xml_rs, xml_rs_parser);
criterion_group!(xml_rs, tiny_xml_rs, medium_xml_rs, large_xml_rs);
fn quick_xml_parser(path: &Path) -> usize {
let mut count = 0;
let mut reader = quick_xml::Reader::from_file(path).unwrap();
let mut buf = Vec::new();
loop {
match reader.read_event_into(&mut buf) {
Ok(quick_xml::events::Event::Start(tag)) | Ok(quick_xml::events::Event::Empty(tag)) => {
count += 1;
for attr in tag.attributes() {
let attr = attr.unwrap();
count += attr.value.len();
}
}
Ok(quick_xml::events::Event::Eof) => {
break;
}
_ => (),
}
}
count
}
bench!(TINY_XML, tiny_quick_xml, quick_xml_parser);
bench!(MEDIUM_XML, medium_quick_xml, quick_xml_parser);
bench!(LARGE_XML, large_quick_xml, quick_xml_parser);
criterion_group!(quick_xml, tiny_quick_xml, medium_quick_xml, large_quick_xml);
mod xml5ever_bench {
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;
use super::*;
use markup5ever::buffer_queue::BufferQueue;
use xml5ever::tendril::*;
use xml5ever::tokenizer::{TagToken, Token, TokenSink, XmlTokenizer};
#[derive(Clone)]
struct TokenCounter {
counter: Arc<AtomicUsize>,
}
impl TokenSink for TokenCounter {
fn process_token(&self, token: Token) {
if let TagToken(tag) = token {
let mut add = tag.name.local.as_ref().len();
for attr in tag.attrs {
add += attr.value.len()
}
self.counter
.fetch_add(add, std::sync::atomic::Ordering::Relaxed);
}
}
}
pub fn xml5ever_parser(path: &Path) -> usize {
let sink = TokenCounter {
counter: Arc::new(AtomicUsize::default()),
};
let mut file = File::open(path).expect("can't open file");
let mut input = ByteTendril::new();
file.read_to_tendril(&mut input).expect("can't read file");
let input_buffer = BufferQueue::default();
input_buffer.push_back(input.try_reinterpret().unwrap());
let tok = XmlTokenizer::new(sink.clone(), Default::default());
tok.feed(&input_buffer);
tok.end();
sink.counter.load(std::sync::atomic::Ordering::Relaxed)
}
}
use xml5ever_bench::xml5ever_parser;
bench!(TINY_XML, tiny_xml5ever, xml5ever_parser);
bench!(MEDIUM_XML, medium_xml5ever, xml5ever_parser);
bench!(LARGE_XML, large_xml5ever, xml5ever_parser);
criterion_group!(xml5ever, tiny_xml5ever, medium_xml5ever, large_xml5ever);
criterion_main!(xml_rs, quick_xml, xml5ever);