Auto merge of #52997 - llogiq:tiny-list-opt, r=varkor

data_structures: make TinyList more readable and optimize remove(_)

also add benchmarks

Before:

```
test tiny_list::test::bench_insert_empty             ... bench:           1 ns/iter (+/- 0)
test tiny_list::test::bench_insert_one               ... bench:          16 ns/iter (+/- 0)
test tiny_list::test::bench_remove_empty             ... bench:           2 ns/iter (+/- 0)
test tiny_list::test::bench_remove_one               ... bench:           6 ns/iter (+/- 0)
test tiny_list::test::bench_remove_unknown           ... bench:           4 ns/iter (+/- 0)
```

After:

```
test tiny_list::test::bench_insert_empty             ... bench:           1 ns/iter (+/- 0)
test tiny_list::test::bench_insert_one               ... bench:          16 ns/iter (+/- 0)
test tiny_list::test::bench_remove_empty             ... bench:           0 ns/iter (+/- 0)
test tiny_list::test::bench_remove_one               ... bench:           3 ns/iter (+/- 0)
test tiny_list::test::bench_remove_unknown           ... bench:           2 ns/iter (+/- 0)
```
This commit is contained in:
bors 2018-08-05 22:41:07 +00:00
commit e9fa9f5a6a

View File

@ -50,44 +50,22 @@ pub fn new_single(data: T) -> TinyList<T> {
#[inline]
pub fn insert(&mut self, data: T) {
let current_head = mem::replace(&mut self.head, None);
if let Some(current_head) = current_head {
let current_head = Box::new(current_head);
self.head = Some(Element {
data,
next: Some(current_head)
});
} else {
self.head = Some(Element {
data,
next: None,
})
}
self.head = Some(Element {
data,
next: mem::replace(&mut self.head, None).map(Box::new),
});
}
#[inline]
pub fn remove(&mut self, data: &T) -> bool {
let remove_head = if let Some(ref mut head) = self.head {
if head.data == *data {
Some(mem::replace(&mut head.next, None))
} else {
None
self.head = match self.head {
Some(ref mut head) if head.data == *data => {
mem::replace(&mut head.next, None).map(|x| *x)
}
} else {
return false
Some(ref mut head) => return head.remove_next(data),
None => return false,
};
if let Some(remove_head) = remove_head {
if let Some(next) = remove_head {
self.head = Some(*next);
} else {
self.head = None;
}
return true
}
self.head.as_mut().unwrap().remove_next(data)
true
}
#[inline]
@ -156,6 +134,8 @@ fn contains(&self, data: &T) -> bool {
#[cfg(test)]
mod test {
use super::*;
extern crate test;
use self::test::Bencher;
#[test]
fn test_contains_and_insert() {
@ -248,4 +228,41 @@ fn test_remove_single() {
assert_eq!(list.len(), 0);
}
#[bench]
fn bench_insert_empty(b: &mut Bencher) {
b.iter(|| {
let mut list = TinyList::new();
list.insert(1);
})
}
#[bench]
fn bench_insert_one(b: &mut Bencher) {
b.iter(|| {
let mut list = TinyList::new_single(0);
list.insert(1);
})
}
#[bench]
fn bench_remove_empty(b: &mut Bencher) {
b.iter(|| {
TinyList::new().remove(&1)
});
}
#[bench]
fn bench_remove_unknown(b: &mut Bencher) {
b.iter(|| {
TinyList::new_single(0).remove(&1)
});
}
#[bench]
fn bench_remove_one(b: &mut Bencher) {
b.iter(|| {
TinyList::new_single(1).remove(&1)
});
}
}