Skip to content

Commit 532990d

Browse files
authored
Merge pull request #386 from Mingun/comparison
Add more XML libraries to comparison
2 parents 9e5de6c + d7781b1 commit 532990d

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

compare/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ edition = "2018"
88

99
[dev-dependencies]
1010
criterion = "0.3"
11+
maybe_xml = "0.2"
1112
quick-xml = { path = "..", features = ["serialize"] }
13+
rapid-xml = "0.2"
14+
rusty_xml = { version = "0.3", package = "RustyXML" }
15+
xml_oxide = "0.3"
1216
xml-rs = "0.8"
17+
xml5ever = "0.17"
18+
xmlparser = "0.13"
1319
serde-xml-rs = "0.5"
1420
serde = { version = "1.0", features = [ "derive" ] }
1521
pretty_assertions = "1.2"

compare/benches/bench.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,134 @@ fn low_level_comparison(c: &mut Criterion) {
2929
})
3030
});
3131

32+
group.bench_function("maybe_xml", |b| {
33+
use maybe_xml::eval::recv::RecvEvaluator;
34+
use maybe_xml::token::borrowed::Token;
35+
36+
b.iter(|| {
37+
let mut input = SOURCE.as_bytes();
38+
let mut eval = RecvEvaluator::new();
39+
40+
let mut count = criterion::black_box(0);
41+
loop {
42+
let consumed = eval.recv(input);
43+
match eval.next_token() {
44+
Ok(Some(Token::StartTag(_))) => count += 1,
45+
Ok(Some(Token::EmptyElementTag(_))) => count += 1,
46+
Ok(Some(Token::Eof)) => break,
47+
Ok(Some(Token::EofWithBytesNotEvaluated(_))) => break,
48+
_ => (),
49+
}
50+
input = &input[consumed..];
51+
}
52+
assert_eq!(count, 1550, "Overall tag count in ./tests/sample_rss.xml");
53+
})
54+
});
55+
56+
group.bench_function("rapid-xml", |b| {
57+
use rapid_xml::parser::{EventCode, Parser};
58+
59+
b.iter(|| {
60+
let mut r = Parser::new(SOURCE.as_bytes());
61+
62+
let mut count = criterion::black_box(0);
63+
loop {
64+
// Makes no progress if error is returned, so need unwrap()
65+
match r.next().unwrap().code() {
66+
EventCode::StartTag => count += 1,
67+
EventCode::Eof => break,
68+
_ => (),
69+
}
70+
}
71+
assert_eq!(count, 1550, "Overall tag count in ./tests/sample_rss.xml");
72+
})
73+
});
74+
75+
group.bench_function("xmlparser", |b| {
76+
use xmlparser::{Token, Tokenizer};
77+
78+
b.iter(|| {
79+
let mut count = criterion::black_box(0);
80+
for token in Tokenizer::from(SOURCE) {
81+
match token {
82+
Ok(Token::ElementStart { .. }) => count += 1,
83+
_ => (),
84+
}
85+
}
86+
assert_eq!(count, 1550, "Overall tag count in ./tests/sample_rss.xml");
87+
})
88+
});
89+
90+
group.bench_function("RustyXML", |b| {
91+
use rusty_xml::{Event, Parser};
92+
93+
b.iter(|| {
94+
let mut r = Parser::new();
95+
r.feed_str(SOURCE);
96+
97+
let mut count = criterion::black_box(0);
98+
for event in r {
99+
match event.unwrap() {
100+
Event::ElementStart(_) => count += 1,
101+
_ => (),
102+
}
103+
}
104+
assert_eq!(count, 1550, "Overall tag count in ./tests/sample_rss.xml");
105+
})
106+
});
107+
108+
group.bench_function("xml_oxide", |b| {
109+
use xml_oxide::sax::parser::Parser;
110+
use xml_oxide::sax::Event;
111+
112+
b.iter(|| {
113+
let mut r = Parser::from_reader(SOURCE.as_bytes());
114+
115+
let mut count = criterion::black_box(0);
116+
loop {
117+
// Makes no progress if error is returned, so need unwrap()
118+
match r.read_event().unwrap() {
119+
Event::StartElement(_) => count += 1,
120+
Event::EndDocument => break,
121+
_ => (),
122+
}
123+
}
124+
assert_eq!(count, 1550, "Overall tag count in ./tests/sample_rss.xml");
125+
})
126+
});
127+
128+
group.bench_function("xml5ever", |b| {
129+
use xml5ever::buffer_queue::BufferQueue;
130+
use xml5ever::tokenizer::{TagKind, Token, TokenSink, XmlTokenizer};
131+
132+
struct Sink(usize);
133+
impl TokenSink for Sink {
134+
fn process_token(&mut self, token: Token) {
135+
match token {
136+
Token::TagToken(tag) if tag.kind == TagKind::StartTag => self.0 += 1,
137+
Token::TagToken(tag) if tag.kind == TagKind::EmptyTag => self.0 += 1,
138+
_ => (),
139+
}
140+
}
141+
}
142+
143+
// Copied from xml5ever benchmarks
144+
// https://github.com/servo/html5ever/blob/429f23943b24f739b78f4d703620d7b1b526475b/xml5ever/benches/xml5ever.rs
145+
b.iter(|| {
146+
let sink = criterion::black_box(Sink(0));
147+
let mut tok = XmlTokenizer::new(sink, Default::default());
148+
let mut buffer = BufferQueue::new();
149+
buffer.push_back(SOURCE.into());
150+
let _ = tok.feed(&mut buffer);
151+
tok.end();
152+
153+
assert_eq!(
154+
tok.sink.0, 1550,
155+
"Overall tag count in ./tests/sample_rss.xml"
156+
);
157+
})
158+
});
159+
32160
group.bench_function("xml_rs", |b| {
33161
b.iter(|| {
34162
let r = EventReader::new(SOURCE.as_bytes());
@@ -84,6 +212,19 @@ fn serde_comparison(c: &mut Criterion) {
84212
})
85213
});
86214

215+
/* NOTE: Most parts of deserializer are not implemented yet, so benchmark failed
216+
group.bench_function("rapid-xml", |b| {
217+
use rapid_xml::de::Deserializer;
218+
use rapid_xml::parser::Parser;
219+
220+
b.iter(|| {
221+
let mut r = Parser::new(SOURCE.as_bytes());
222+
let mut de = Deserializer::new(&mut r).unwrap();
223+
let rss = Rss::deserialize(&mut de).unwrap();
224+
assert_eq!(rss.channel.items.len(), 99);
225+
});
226+
});*/
227+
87228
group.bench_function("xml_rs", |b| {
88229
b.iter(|| {
89230
let rss: Rss = serde_xml_rs::from_str(SOURCE).unwrap();

0 commit comments

Comments
 (0)