diff --git a/core/benches/sumtree.rs b/core/benches/sumtree.rs new file mode 100644 index 000000000..e8abfb697 --- /dev/null +++ b/core/benches/sumtree.rs @@ -0,0 +1,75 @@ +// Copyright 2016 The Grin Developers +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![feature(test)] + +extern crate test; +extern crate rand; +extern crate grin_core as core; + +use rand::Rng; +use test::Bencher; + +use core::core::sumtree::{self, SumTree, Summable}; +use core::ser::{Writeable, Writer, Error}; + +#[derive(Copy, Clone, Debug)] +struct TestElem([u32; 4]); +impl Summable for TestElem { + type Sum = u64; + fn sum(&self) -> u64 { + // sums are not allowed to overflow, so we use this simple + // non-injective "sum" function that will still be homomorphic + self.0[0] as u64 * 0x1000 + self.0[1] as u64 * 0x100 + self.0[2] as u64 * 0x10 + + self.0[3] as u64 + } +} + +impl Writeable for TestElem { + fn write(&self, writer: &mut W) -> Result<(), Error> { + try!(writer.write_u32(self.0[0])); + try!(writer.write_u32(self.0[1])); + try!(writer.write_u32(self.0[2])); + writer.write_u32(self.0[3]) + } +} + +#[bench] +fn bench_small_tree(b: &mut Bencher) { + let mut rng = rand::thread_rng(); + b.iter(|| { + let mut big_tree = SumTree::new(); + for i in 0..1000 { + // To avoid RNG overflow we generate random elements that are small. + // Though to avoid repeat elements they have to be reasonably big. + let new_elem; + let word1 = rng.gen::() as u32; + let word2 = rng.gen::() as u32; + if rng.gen() { + if rng.gen() { + new_elem = TestElem([word1, word2, 0, 0]); + } else { + new_elem = TestElem([word1, 0, word2, 0]); + } + } else { + if rng.gen() { + new_elem = TestElem([0, word1, 0, word2]); + } else { + new_elem = TestElem([0, 0, word1, word2]); + } + } + + big_tree.push(new_elem); + } + }); +} diff --git a/core/src/core/sumtree.rs b/core/src/core/sumtree.rs index 2f13a1bd0..724f4166b 100644 --- a/core/src/core/sumtree.rs +++ b/core/src/core/sumtree.rs @@ -653,7 +653,7 @@ where } #[allow(dead_code)] -fn print_tree(tree: &SumTree) +pub fn print_tree(tree: &SumTree) where T: Summable + Writeable, T::Sum: std::fmt::Debug, @@ -848,7 +848,7 @@ mod test { assert_eq!(tree.root_sum(), Some((expected, 28 + 0x1000))); assert_eq!(tree.root_sum(), compute_root(elems[0..8].iter())); assert_eq!(tree.unpruned_len(), 8); - prune!(prune, tree, elems[7]); + prune!(prune, tree, elems[7]); // If we weren't pruning, try changing some elements if !prune {