collections: Use slices parts in PartialEq for VecDeque

This improves == for VecDeque by using the slice representation.

This will also improve further if codegen for slice comparison improves.

Benchmark run of 1000 u64 elements, comparing for equality (all equal).
Cpu time to compare the vecdeques is reduced to less than 50% of what it
was before.

```
test test_eq_u64       ... bench:  1,885 ns/iter (+/- 163) = 4244 MB/s
test test_eq_new_u64   ... bench:    802 ns/iter (+/- 100) = 9975 MB/s
```
This commit is contained in:
Ulrik Sverdrup 2016-01-27 00:35:03 +01:00
parent d3174ce751
commit aeb3aba951
2 changed files with 60 additions and 1 deletions

View File

@ -1968,7 +1968,39 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: PartialEq> PartialEq for VecDeque<A> {
fn eq(&self, other: &VecDeque<A>) -> bool {
self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a.eq(b))
if self.len() != other.len() {
return false;
}
let (sa, sb) = self.as_slices();
let (oa, ob) = other.as_slices();
if sa.len() == oa.len() {
sa == oa && sb == ob
} else if sa.len() < oa.len() {
// Always divisible in three sections, for example:
// self: [a b c|d e f]
// other: [0 1 2 3|4 5]
// front = 3, mid = 1,
// [a b c] == [0 1 2] && [d] == [3] && [e f] == [4 5]
let front = sa.len();
let mid = oa.len() - front;
let (oa_front, oa_mid) = oa.split_at(front);
let (sb_mid, sb_back) = sb.split_at(mid);
debug_assert_eq!(sa.len(), oa_front.len());
debug_assert_eq!(sb_mid.len(), oa_mid.len());
debug_assert_eq!(sb_back.len(), ob.len());
sa == oa_front && sb_mid == oa_mid && sb_back == ob
} else {
let front = oa.len();
let mid = sa.len() - front;
let (sa_front, sa_mid) = sa.split_at(front);
let (ob_mid, ob_back) = ob.split_at(mid);
debug_assert_eq!(sa_front.len(), oa.len());
debug_assert_eq!(sa_mid.len(), ob_mid.len());
debug_assert_eq!(sb.len(), ob_back.len());
sa_front == oa && sa_mid == ob_mid && sb == ob_back
}
}
}

View File

@ -624,6 +624,33 @@ fn test_hash_after_rotation() {
}
}
#[test]
fn test_eq_after_rotation() {
// test that two deques are equal even if elements are laid out differently
let len = 28;
let mut ring: VecDeque<i32> = (0..len as i32).collect();
let mut shifted = ring.clone();
for _ in 0..10 {
// 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);
}
// try every shift
for _ in 0..shifted.capacity() {
shifted.pop_front();
for elt in &mut shifted {
*elt -= 1;
}
shifted.push_back(len - 1);
assert_eq!(shifted, ring);
assert_eq!(ring, shifted);
}
}
#[test]
fn test_ord() {
let x = VecDeque::new();