From 386b53cce743230858ab386fc21bc24bc2d80304 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Mon, 26 May 2014 09:23:05 -0700 Subject: [PATCH] Add a bench_map. test bench_map::bench_decoder_map_000 ... bench: 510 ns/iter (+/- 124) test bench_map::bench_decoder_map_003 ... bench: 2347 ns/iter (+/- 253) test bench_map::bench_decoder_map_100 ... bench: 68735 ns/iter (+/- 14869) test bench_map::bench_deserializer_map_000 ... bench: 736 ns/iter (+/- 35) test bench_map::bench_deserializer_map_003 ... bench: 2446 ns/iter (+/- 348) test bench_map::bench_deserializer_map_100 ... bench: 64326 ns/iter (+/- 15191) --- bench_map.rs | 315 +++++++++++++++++++++++++++++++++++++++++++++++++++ serde.rs | 3 + 2 files changed, 318 insertions(+) create mode 100644 bench_map.rs diff --git a/bench_map.rs b/bench_map.rs new file mode 100644 index 00000000..575da966 --- /dev/null +++ b/bench_map.rs @@ -0,0 +1,315 @@ +use std::fmt::Show; +use collections::HashMap; +use test::Bencher; + +use serialize::{Decoder, Decodable}; + +use de::{Deserializer, Deserializable}; + +////////////////////////////////////////////////////////////////////////////// + +#[deriving(Show)] +enum Error { + EndOfStream, + SyntaxError, +} + +////////////////////////////////////////////////////////////////////////////// + +mod decoder { + use collections::HashMap; + use collections::hashmap::MoveEntries; + use serialize; + + use super::{Error, EndOfStream, SyntaxError}; + + enum Value { + StringValue(String), + IntValue(int), + } + + pub struct IntDecoder { + len: uint, + iter: MoveEntries, + stack: Vec, + } + + impl IntDecoder { + #[inline] + pub fn new(values: HashMap) -> IntDecoder { + IntDecoder { + len: values.len(), + iter: values.move_iter(), + stack: vec!(), + } + } + } + + impl serialize::Decoder for IntDecoder { + // Primitive types: + fn read_nil(&mut self) -> Result<(), Error> { Err(SyntaxError) } + fn read_uint(&mut self) -> Result { Err(SyntaxError) } + fn read_u64(&mut self) -> Result { Err(SyntaxError) } + fn read_u32(&mut self) -> Result { Err(SyntaxError) } + fn read_u16(&mut self) -> Result { Err(SyntaxError) } + fn read_u8(&mut self) -> Result { Err(SyntaxError) } + #[inline] + fn read_int(&mut self) -> Result { + match self.stack.pop() { + Some(IntValue(x)) => Ok(x), + Some(_) => Err(SyntaxError), + None => Err(EndOfStream), + } + } + fn read_i64(&mut self) -> Result { Err(SyntaxError) } + fn read_i32(&mut self) -> Result { Err(SyntaxError) } + fn read_i16(&mut self) -> Result { Err(SyntaxError) } + fn read_i8(&mut self) -> Result { Err(SyntaxError) } + fn read_bool(&mut self) -> Result { Err(SyntaxError) } + fn read_f64(&mut self) -> Result { Err(SyntaxError) } + fn read_f32(&mut self) -> Result { Err(SyntaxError) } + fn read_char(&mut self) -> Result { Err(SyntaxError) } + #[inline] + fn read_str(&mut self) -> Result { + match self.stack.pop() { + Some(StringValue(x)) => Ok(x), + Some(_) => Err(SyntaxError), + None => Err(EndOfStream), + } + } + + // Compound types: + fn read_enum(&mut self, _name: &str, _f: |&mut IntDecoder| -> Result) -> Result { Err(SyntaxError) } + + fn read_enum_variant(&mut self, + _names: &[&str], + _f: |&mut IntDecoder, uint| -> Result) + -> Result { Err(SyntaxError) } + fn read_enum_variant_arg(&mut self, + _a_idx: uint, + _f: |&mut IntDecoder| -> Result) + -> Result { Err(SyntaxError) } + + fn read_enum_struct_variant(&mut self, + _names: &[&str], + _f: |&mut IntDecoder, uint| -> Result) + -> Result { Err(SyntaxError) } + fn read_enum_struct_variant_field(&mut self, + _f_name: &str, + _f_idx: uint, + _f: |&mut IntDecoder| -> Result) + -> Result { Err(SyntaxError) } + + fn read_struct(&mut self, _s_name: &str, _len: uint, _f: |&mut IntDecoder| -> Result) + -> Result { Err(SyntaxError) } + fn read_struct_field(&mut self, + _f_name: &str, + _f_idx: uint, + _f: |&mut IntDecoder| -> Result) + -> Result { Err(SyntaxError) } + + fn read_tuple(&mut self, _f: |&mut IntDecoder, uint| -> Result) -> Result { Err(SyntaxError) } + fn read_tuple_arg(&mut self, _a_idx: uint, _f: |&mut IntDecoder| -> Result) -> Result { Err(SyntaxError) } + + fn read_tuple_struct(&mut self, + _s_name: &str, + _f: |&mut IntDecoder, uint| -> Result) + -> Result { Err(SyntaxError) } + fn read_tuple_struct_arg(&mut self, + _a_idx: uint, + _f: |&mut IntDecoder| -> Result) + -> Result { Err(SyntaxError) } + + // Specialized types: + fn read_option(&mut self, _f: |&mut IntDecoder, bool| -> Result) -> Result { Err(SyntaxError) } + + fn read_seq(&mut self, _f: |&mut IntDecoder, uint| -> Result) -> Result { Err(SyntaxError) } + fn read_seq_elt(&mut self, _idx: uint, _f: |&mut IntDecoder| -> Result) -> Result { Err(SyntaxError) } + + #[inline] + fn read_map(&mut self, f: |&mut IntDecoder, uint| -> Result) -> Result { + f(self, self.len) + } + #[inline] + fn read_map_elt_key(&mut self, _idx: uint, f: |&mut IntDecoder| -> Result) -> Result { + match self.iter.next() { + Some((key, value)) => { + self.stack.push(IntValue(value)); + self.stack.push(StringValue(key)); + f(self) + } + None => { + Err(SyntaxError) + } + } + } + #[inline] + fn read_map_elt_val(&mut self, _idx: uint, f: |&mut IntDecoder| -> Result) -> Result { + f(self) + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +mod deserializer { + use collections::HashMap; + use collections::hashmap::MoveEntries; + + use super::{Error, EndOfStream, SyntaxError}; + + use de; + + #[deriving(Eq, Show)] + enum State { + StartState, + KeyOrEndState, + ValueState(int), + EndState, + } + + pub struct IntDeserializer { + stack: Vec, + len: uint, + iter: MoveEntries, + } + + impl IntDeserializer { + #[inline] + pub fn new(values: HashMap) -> IntDeserializer { + IntDeserializer { + stack: vec!(StartState), + len: values.len(), + iter: values.move_iter(), + } + } + } + + impl Iterator> for IntDeserializer { + #[inline] + fn next(&mut self) -> Option> { + match self.stack.pop() { + Some(StartState) => { + self.stack.push(KeyOrEndState); + Some(Ok(de::MapStart(self.len))) + } + Some(KeyOrEndState) => { + match self.iter.next() { + Some((key, value)) => { + self.stack.push(ValueState(value)); + Some(Ok(de::String(key))) + } + None => { + self.stack.push(EndState); + Some(Ok(de::End)) + } + } + } + Some(ValueState(x)) => { + self.stack.push(KeyOrEndState); + Some(Ok(de::Int(x))) + } + Some(EndState) => { + None + } + None => { + None + } + } + } + } + + impl de::Deserializer for IntDeserializer { + #[inline] + fn end_of_stream_error(&self) -> Error { + EndOfStream + } + + #[inline] + fn syntax_error(&self) -> Error { + SyntaxError + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +fn run_decoder< + E: Show, + D: Decoder, + T: Clone + Eq + Show + Decodable +>(mut d: D, value: T) { + let v: T = Decodable::decode(&mut d).unwrap(); + + assert_eq!(value, v); +} + +#[bench] +fn bench_decoder_map_000(b: &mut Bencher) { + b.iter(|| { + let m: HashMap = HashMap::new(); + run_decoder(decoder::IntDecoder::new(m.clone()), m) + }) +} + +#[bench] +fn bench_decoder_map_003(b: &mut Bencher) { + b.iter(|| { + let mut m: HashMap = HashMap::new(); + for i in range(0, 3) { + m.insert(i.to_str(), i); + } + run_decoder(decoder::IntDecoder::new(m.clone()), m) + }) +} + +#[bench] +fn bench_decoder_map_100(b: &mut Bencher) { + b.iter(|| { + let mut m: HashMap = HashMap::new(); + for i in range(0, 100) { + m.insert(i.to_str(), i); + } + run_decoder(decoder::IntDecoder::new(m.clone()), m) + }) +} + +fn run_deserializer< + E: Show, + D: Deserializer, + T: Clone + Eq + Show + Deserializable +>(mut d: D, value: T) { + let v: T = Deserializable::deserialize(&mut d).unwrap(); + + assert_eq!(value, v); +} + +#[bench] +fn bench_deserializer_map_000(b: &mut Bencher) { + b.iter(|| { + let m: HashMap = HashMap::new(); + run_deserializer(deserializer::IntDeserializer::new(m.clone()), m) + }) +} + +#[bench] +fn bench_deserializer_map_003(b: &mut Bencher) { + b.iter(|| { + let mut m: HashMap = HashMap::new(); + for i in range(0, 3) { + m.insert(i.to_str(), i); + } + run_deserializer(deserializer::IntDeserializer::new(m.clone()), m) + }) +} + +#[bench] +fn bench_deserializer_map_100(b: &mut Bencher) { + b.iter(|| { + let mut m: HashMap = HashMap::new(); + for i in range(0, 100) { + m.insert(i.to_str(), i); + } + run_deserializer(deserializer::IntDeserializer::new(m.clone()), m) + }) +} diff --git a/serde.rs b/serde.rs index e7783317..2014d8b6 100644 --- a/serde.rs +++ b/serde.rs @@ -25,3 +25,6 @@ pub mod bench_struct; //#[cfg(test)] //pub mod bench_vec; + +#[cfg(test)] +pub mod bench_map;