Auto merge of #31224 - bluss:deque-hashing, r=Gankro

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
```
This commit is contained in:
bors 2016-01-27 16:25:36 +00:00
commit b2f4c5c596
2 changed files with 22 additions and 3 deletions

View File

@ -1994,9 +1994,9 @@ impl<A: Ord> Ord for VecDeque<A> {
impl<A: Hash> Hash for VecDeque<A> {
fn hash<H: Hasher>(&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);
}
}

View File

@ -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<i32> = (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();