Skip to content

Commit

Permalink
Merge pull request #22 from ArazAbishov/iter
Browse files Browse the repository at this point in the history
Iterator implementation
  • Loading branch information
arazabishov committed Apr 22, 2019
2 parents 7dbf7d1 + 1ba0716 commit 1887c4d
Show file tree
Hide file tree
Showing 5 changed files with 477 additions and 101 deletions.
180 changes: 136 additions & 44 deletions benches/lib-criterion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extern crate pvec;
extern crate rand;
extern crate test as test_crate;

use criterion::{BatchSize, Criterion, ParameterizedBenchmark};
use criterion::{black_box, BatchSize, Criterion, ParameterizedBenchmark};
use dogged::DVec;
use im::Vector as IVec;
use rand::{Rng, SeedableRng, XorShiftRng};
Expand Down Expand Up @@ -196,58 +196,82 @@ fn index_sequentially(criterion: &mut Criterion) {
ParameterizedBenchmark::new(
"std",
|bencher, n| {
let mut vec = Vec::new();
bencher.iter_batched(
|| {
let mut vec = Vec::new();

for i in 0..*n {
vec.push(i * 2);
}
for i in 0..*n {
vec.push(i * 2);
}

bencher.iter(|| {
for i in 0..*n {
let _ = vec[i];
}
})
vec
},
|data| {
for i in 0..*n {
black_box(data[i]);
}
},
BatchSize::SmallInput,
)
},
vec![100, 500, 1000, 5000, 10000, 50000, 100000, 200000, 500000],
)
.with_function("dvec", |bencher, n| {
let mut vec = DVec::new();
bencher.iter_batched(
|| {
let mut vec = DVec::new();

for i in 0..*n {
vec.push(i * 2);
}
for i in 0..*n {
vec.push(i * 2);
}

bencher.iter(|| {
for i in 0..*n {
let _ = vec[i];
}
});
vec
},
|data| {
for i in 0..*n {
black_box(data[i]);
}
},
BatchSize::SmallInput,
)
})
.with_function("im-rs", |bencher, n| {
let mut vec = IVec::new();
bencher.iter_batched(
|| {
let mut vec = IVec::new();

for i in 0..*n {
vec.push_back(i * 2);
}
for i in 0..*n {
vec.push_back(i * 2);
}

bencher.iter(|| {
for i in 0..*n {
let _ = vec[i];
}
});
vec
},
|data| {
for i in 0..*n {
black_box(data[i]);
}
},
BatchSize::SmallInput,
)
})
.with_function("pvec", |bencher, n| {
let mut vec = PVec::new();
bencher.iter_batched(
|| {
let mut vec = PVec::new();

for i in 0..*n {
vec.push(i * 2);
}
for i in 0..*n {
vec.push(i * 2);
}

bencher.iter(|| {
for i in 0..*n {
let _ = vec[i];
}
});
vec
},
|data| {
for i in 0..*n {
black_box(data[i]);
}
},
BatchSize::SmallInput,
)
}),
);
}
Expand Down Expand Up @@ -543,15 +567,83 @@ fn append_push(criterion: &mut Criterion) {
);
}

fn iterator(criterion: &mut Criterion) {
criterion.bench(
"iterator",
ParameterizedBenchmark::new(
"std",
|bencher, n| {
bencher.iter_batched(
|| {
let mut vec = Vec::new();

for i in 0..*n {
vec.push(i * 2);
}

vec
},
|data| {
for i in data.into_iter() {
black_box(i);
}
},
BatchSize::SmallInput,
)
},
vec![100, 500, 1000, 5000, 10000, 50000, 100000, 200000, 500000],
)
.with_function("im-rs", |bencher, n| {
bencher.iter_batched(
|| {
let mut vec = IVec::new();

for i in 0..*n {
vec.push_back(i * 2);
}

vec
},
|data| {
for i in data.into_iter() {
black_box(i);
}
},
BatchSize::SmallInput,
)
})
.with_function("pvec", |bencher, n| {
bencher.iter_batched(
|| {
let mut vec = PVec::new();

for i in 0..*n {
vec.push(i * 2);
}

vec
},
|data| {
for i in data.into_iter() {
black_box(i);
}
},
BatchSize::SmallInput,
)
}),
);
}

criterion_group!(
benches,
push,
push_clone,
pop_clone,
// push,
// push_clone,
// pop_clone,
index_sequentially,
index_randomly,
append,
append_clone,
append_push
iterator,
// index_randomly,
// append,
// append_clone,
// append_push
);
criterion_main!(benches);
152 changes: 146 additions & 6 deletions src/iter.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,55 @@
use super::PVec;
use rrbtree::iter::RrbTreeIter;
use rrbtree::BRANCH_FACTOR;
use std::fmt::Debug;

#[derive(Debug, Clone)]
pub struct PVecIter<T> {
// - you should avoid heap allocation in iterators
pvec: PVec<T>,
len: usize,
tree_iter: RrbTreeIter<T>,
tree_len: usize,
tail: [Option<T>; BRANCH_FACTOR],
tail_len: usize,
index: usize,
chunk: Option<([Option<T>; BRANCH_FACTOR], usize)>,
chunk_index: usize,
}

impl<T: Clone + Debug> Iterator for PVecIter<T> {
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
return None;
return if self.index < self.tree_len {
if self.chunk.is_none() {
self.chunk = self.tree_iter.next();
}

let chunk = self.chunk.as_mut().unwrap();
if self.chunk_index >= chunk.1 {
self.chunk_index = 0;
self.chunk = self.tree_iter.next();
}

let chunk = self.chunk.as_mut().unwrap();
let value = chunk.0[self.chunk_index].take();

self.chunk_index += 1;
self.index += 1;

value
} else if self.index < self.tree_len + self.tail_len {
let index = self.index - self.tree_len;

self.index += 1;
self.tail[index].take()
} else {
None
};
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
let len = self.tree_len + self.tail_len;
(len, Some(len))
}
}

Expand All @@ -26,8 +59,115 @@ impl<T: Clone + Debug> IntoIterator for PVec<T> {

fn into_iter(self) -> Self::IntoIter {
PVecIter {
len: self.len(),
pvec: self,
tree_len: self.tree.len(),
tree_iter: self.tree.into_iter(),
tail_len: self.tail_len,
tail: self.tail,
index: 0,
chunk: None,
chunk_index: 0,
}
}
}

#[cfg(test)]
#[macro_use]
mod test {
use super::PVec;
use super::BRANCH_FACTOR;

#[test]
fn empty_pvec() {
let pvec: PVec<usize> = PVec::new();
let mut iter = pvec.into_iter();

let size = iter.size_hint();
let next = iter.next();

assert_eq!(next, None);
assert_eq!(size, (0, Some(0)));
}

#[test]
fn pvec_has_tail_only() {
let mut pvec = PVec::new();

for i in 0..BRANCH_FACTOR {
pvec.push(i);
}

for (i, val) in pvec.into_iter().enumerate() {
assert_eq!(i, val);
}
}

#[test]
fn underlying_tree_has_multiple_levels() {
let mut pvec = PVec::new();

let mut val = 0;
for _ in 0..(BRANCH_FACTOR * BRANCH_FACTOR * BRANCH_FACTOR) {
pvec.push(val);
val += 1;
}

for _ in 0..(BRANCH_FACTOR / 2) {
pvec.push(val);
val += 1;
}

for (i, val) in pvec.into_iter().enumerate() {
assert_eq!(i, val);
}
}

#[test]
fn underlying_tree_is_relaxed() {
let vec_size = 33;

let mut vec = PVec::new();
let mut vec_item = 0;

for i in 0..128 {
if i % 2 == 0 {
let mut vec_temp = PVec::new();

for _ in 0..vec_size {
vec_temp.push(vec_item);
vec_item += 1;
}

assert_eq!(vec_temp.len(), vec_size);

vec.append(&mut vec_temp);

assert_eq!(vec_temp.len(), 0);
} else {
for _ in 0..(vec_size + vec_size) {
vec.push(vec_item);
vec_item += 1;
}
}

assert_eq!(vec.len(), vec_item);

for i in 0..vec.len() {
assert_eq!(*vec.get(i).unwrap(), i);
assert_eq!(*vec.get_mut(i).unwrap(), i);
}

let mut vec_one_clone = vec.clone();
for i in (0..vec_item).rev() {
assert_eq!(vec_one_clone.pop().unwrap(), i);
}

assert_eq!(vec_one_clone.len(), 0);
assert_eq!(vec.len(), vec_item);

let vec_clone = vec.clone();
for (i, val) in vec_clone.into_iter().enumerate() {
assert_eq!(i, val);
}
}
}
}
Loading

0 comments on commit 1887c4d

Please sign in to comment.