Skip to content

Commit c0e49f9

Browse files
committed
0.7.1 benchmark serialization
1 parent ede49b6 commit c0e49f9

File tree

3 files changed

+96
-62
lines changed

3 files changed

+96
-62
lines changed

benches/lib.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use test::Bencher;
1111
const JSON_STR: &'static str = r#"{"timestamp":2837513946597,"zone_id":123456,"zone_plan":1,"http":{"protocol":2,"status":200,"host_status":503,"up_status":520,"method":1,"content_type":"text/html","user_agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36","referer":"https://www.cloudflare.com/","request_uri":"/cdn-cgi/trace"},"origin":{"ip":"1.2.3.4","port":8000,"hostname":"www.example.com","protocol":2},"country":238,"cache_status":3,"server_ip":"192.168.1.1","server_name":"metal.cloudflare.com","remote_ip":"10.1.2.3","bytes_dlv":123456,"ray_id":"10c73629cce30078-LAX","true":true,"false":false,"null":null}"#;
1212

1313
#[bench]
14-
fn bench_serde_value(b: &mut Bencher) {
14+
fn serde_json_parse(b: &mut Bencher) {
1515
b.bytes = JSON_STR.len() as u64;
1616

1717
b.iter(|| {
@@ -20,12 +20,32 @@ fn bench_serde_value(b: &mut Bencher) {
2020
}
2121

2222
#[bench]
23-
fn bench_json_rust(b: &mut Bencher) {
24-
extern crate json;
23+
fn serde_json_stringify(b: &mut Bencher) {
24+
b.bytes = JSON_STR.len() as u64;
25+
26+
let data = serde_json::from_str::<serde_json::Value>(JSON_STR).unwrap();
2527

28+
b.iter(|| {
29+
serde_json::to_string(&data).unwrap()
30+
})
31+
}
32+
33+
#[bench]
34+
fn json_rust_parse(b: &mut Bencher) {
2635
b.bytes = JSON_STR.len() as u64;
2736

2837
b.iter(|| {
2938
json::parse(JSON_STR).unwrap()
3039
});
3140
}
41+
42+
#[bench]
43+
fn json_rust_stringify(b: &mut Bencher) {
44+
b.bytes = JSON_STR.len() as u64;
45+
46+
let data = json::parse(JSON_STR).unwrap();
47+
48+
b.iter(|| {
49+
data.dump()
50+
})
51+
}

src/codegen.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ impl Generator {
1111
pub fn new(minify: bool, spaces: u16) -> Self {
1212
Generator {
1313
minify: minify,
14-
code: String::new(),
14+
code: String::with_capacity(1024),
1515
dent: 0,
1616
spaces_per_indent: spaces
1717
}

src/parser.rs

Lines changed: 72 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::char;
22
use std::str;
33
use std::str::Bytes;
4-
use std::iter::{ Peekable, Iterator };
54
use std::collections::BTreeMap;
65
use { JsonValue, JsonError, JsonResult };
76

@@ -29,26 +28,63 @@ macro_rules! expect_char {
2928
}
3029
}
3130

31+
macro_rules! read_num {
32+
($tok:ident, $num:ident, $then:expr) => {
33+
while let Some(ch) = $tok.next_byte() {
34+
match ch {
35+
b'0' ... b'9' => {
36+
let $num = ch - b'0';
37+
$then;
38+
},
39+
ch => {
40+
$tok.left_over = Some(ch);
41+
break;
42+
}
43+
}
44+
}
45+
}
46+
}
47+
3248
struct Tokenizer<'a> {
33-
source: Peekable<Bytes<'a>>,
49+
source: Bytes<'a>,
3450
buffer: Vec<u8>,
51+
left_over: Option<u8>,
3552
}
3653

3754
impl<'a> Tokenizer<'a> {
3855
pub fn new(source: &'a str) -> Self {
3956
Tokenizer {
40-
source: source.bytes().peekable(),
41-
buffer: Vec::with_capacity(500)
57+
source: source.bytes(),
58+
buffer: Vec::with_capacity(512),
59+
left_over: None,
60+
}
61+
}
62+
63+
fn peek_byte(&mut self) -> Option<u8> {
64+
if self.left_over.is_none() {
65+
self.left_over = self.source.next();
66+
}
67+
68+
return self.left_over;
69+
}
70+
71+
fn next_byte(&mut self) -> Option<u8> {
72+
if self.left_over.is_some() {
73+
let byte = self.left_over;
74+
self.left_over = None;
75+
return byte;
4276
}
77+
78+
self.source.next()
4379
}
4480

4581
#[inline(always)]
46-
fn expect(&mut self) -> JsonResult<u8> {
47-
self.source.next().ok_or(JsonError::UnexpectedEndOfJson)
82+
fn expect_byte(&mut self) -> JsonResult<u8> {
83+
self.next_byte().ok_or(JsonError::UnexpectedEndOfJson)
4884
}
4985

5086
fn read_char_as_hexnumber(&mut self) -> JsonResult<u32> {
51-
let ch = try!(self.expect());
87+
let ch = try!(self.expect_byte());
5288
Ok(match ch {
5389
b'0' ... b'9' => (ch - b'0') as u32,
5490
b'a' ... b'f' => (ch + 10 - b'a') as u32,
@@ -78,11 +114,11 @@ impl<'a> Tokenizer<'a> {
78114
self.buffer.clear();
79115

80116
loop {
81-
let ch = try!(self.expect());
117+
let ch = try!(self.expect_byte());
82118
match ch {
83119
b'"' => break,
84120
b'\\' => {
85-
let ch = try!(self.expect());
121+
let ch = try!(self.expect_byte());
86122
let ch = match ch {
87123
b'b' => 0x8,
88124
b'f' => 0xC,
@@ -108,79 +144,57 @@ impl<'a> Tokenizer<'a> {
108144
fn read_number(&mut self, first: u8) -> JsonResult<f64> {
109145
let mut num = if first == b'-' { 0 } else { (first - b'0') as u64 };
110146

111-
while let Some(&ch) = self.source.peek() {
112-
match ch {
113-
b'0' ... b'9' => {
114-
num = num * 10 + (ch - b'0') as u64;
115-
},
116-
_ => break
117-
}
118-
self.source.next();
119-
}
147+
read_num!(self, digit, num = num * 10 + digit as u64);
120148

121-
match self.source.peek() {
122-
Some(&b'.') | Some(&b'e') | Some(&b'E') => {},
123-
_ => return Ok(if first == b'-' {
124-
(num as f64) * -1.0
125-
} else {
126-
num as f64
127-
})
149+
match self.peek_byte() {
150+
Some(b'.') | Some(b'e') | Some(b'E') => {},
151+
_ => {
152+
return if first == b'-' {
153+
Ok((num as f64) * -1.0)
154+
} else {
155+
Ok(num as f64)
156+
};
157+
}
128158
}
129159

130160
let mut num = num as f64;
131161

132-
if let Some(&b'.') = self.source.peek() {
133-
self.source.next();
162+
if let Some(b'.') = self.peek_byte() {
163+
self.next_byte();
134164

135165
let mut precision = -1;
136-
while let Some(&ch) = self.source.peek() {
137-
match ch {
138-
b'0' ... b'9' => {
139-
num += ((ch - b'0') as f64) * 10f64.powi(precision);
140-
precision -= 1;
141-
},
142-
_ => break
143-
}
144-
self.source.next();
145-
}
146-
}
147166

148-
match self.source.peek() {
149-
Some(&b'e') | Some(&b'E') => {
150-
self.source.next();
167+
read_num!(self, digit, {
168+
num += (digit as f64) * 10_f64.powi(precision);
169+
precision -= 1;
170+
});
171+
}
151172

173+
match self.next_byte() {
174+
Some(b'e') | Some(b'E') => {
152175
let mut e = 0;
153-
let sign = match self.source.peek() {
154-
Some(&b'-') => {
155-
self.source.next();
156-
-1
157-
},
158-
Some(&b'+') => {
159-
self.source.next();
176+
let sign = match self.next_byte() {
177+
Some(b'-') => -1,
178+
Some(b'+') => 1,
179+
byte => {
180+
self.left_over = byte;
160181
1
161182
},
162-
_ => 1
163183
};
164184

165-
while let Some(&ch) = self.source.peek() {
166-
match ch {
167-
b'0' ... b'9' => e = e * 10 + (ch - b'0') as i32,
168-
_ => break
169-
}
170-
self.source.next();
171-
}
185+
read_num!(self, digit, e = e * 10 + digit as i32);
172186

173187
num *= 10f64.powi(e * sign);
174188
},
175-
_ => {}
189+
byte => self.left_over = byte
176190
}
177191

178192
Ok(if first == b'-' { num * -1.0 } else { num })
179193
}
180194

181195
fn next(&mut self) -> JsonResult<Token> {
182196
loop {
183-
let ch = try!(self.expect());
197+
let ch = try!(self.expect_byte());
184198
return Ok(match ch {
185199
b',' => Token::Comma,
186200
b':' => Token::Colon,

0 commit comments

Comments
 (0)