From d3174ce75112a52082580065b041f8f4330fefa5 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Tue, 26 Jan 2016 21:31:33 +0100 Subject: [PATCH] collections: Hash VecDeque in its slice parts Use .as_slices() for a more efficient code path in VecDeque's Hash impl. This still hashes the elements in the same order. Before/after timing of VecDeque hashing 1024 elements of u8 and u64 shows that the vecdeque now can match the Vec (test_hashing_vec_of_u64 is the Vec run). before test test_hashing_u64 ... bench: 14,031 ns/iter (+/- 236) = 583 MB/s test test_hashing_u8 ... bench: 7,887 ns/iter (+/- 65) = 129 MB/s test test_hashing_vec_of_u64 ... bench: 6,578 ns/iter (+/- 76) = 1245 MB/s after running 5 tests test test_hashing_u64 ... bench: 6,495 ns/iter (+/- 52) = 1261 MB/s test test_hashing_u8 ... bench: 851 ns/iter (+/- 16) = 1203 MB/s test test_hashing_vec_of_u64 ... bench: 6,499 ns/iter (+/- 59) = 1260 MB/s --- src/libcollections/vec_deque.rs | 6 +++--- src/libcollectionstest/vec_deque.rs | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 394f7a97598..f434053390e 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1994,9 +1994,9 @@ impl Ord for VecDeque { impl Hash for VecDeque { fn hash(&self, state: &mut H) { self.len().hash(state); - for elt in self { - elt.hash(state); - } + let (a, b) = self.as_slices(); + Hash::hash_slice(a, state); + Hash::hash_slice(b, state); } } diff --git a/src/libcollectionstest/vec_deque.rs b/src/libcollectionstest/vec_deque.rs index 5f587789bd8..a50886bfdf3 100644 --- a/src/libcollectionstest/vec_deque.rs +++ b/src/libcollectionstest/vec_deque.rs @@ -605,6 +605,25 @@ fn test_hash() { assert!(::hash(&x) == ::hash(&y)); } +#[test] +fn test_hash_after_rotation() { + // test that two deques hash equal even if elements are laid out differently + let len = 28; + let mut ring: VecDeque = (0..len as i32).collect(); + let orig = ring.clone(); + for _ in 0..ring.capacity() { + // shift values 1 step to the right by pop, sub one, push + ring.pop_front(); + for elt in &mut ring { + *elt -= 1; + } + ring.push_back(len - 1); + assert_eq!(::hash(&orig), ::hash(&ring)); + assert_eq!(orig, ring); + assert_eq!(ring, orig); + } +} + #[test] fn test_ord() { let x = VecDeque::new();