Skip to content

Commit d682f4a

Browse files
authored
Merge pull request #81 from Dr-Emann/multi_iter
Expose the ability to read multiple items from an iterator, for performance
2 parents 5557373 + 5961a26 commit d682f4a

File tree

2 files changed

+75
-5
lines changed

2 files changed

+75
-5
lines changed

croaring/src/bitmap/iter.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ use std::marker::PhantomData;
33

44
use super::Bitmap;
55

6+
#[derive(Clone)]
67
pub struct BitmapIterator<'a> {
78
iterator: ffi::roaring_uint32_iterator_s,
89
phantom: PhantomData<&'a Bitmap>,
910
}
1011

12+
unsafe impl Send for BitmapIterator<'_> {}
13+
unsafe impl Sync for BitmapIterator<'_> {}
14+
1115
impl<'a> BitmapIterator<'a> {
1216
fn new(bitmap: &'a Bitmap) -> Self {
1317
let mut iterator = std::mem::MaybeUninit::uninit();
@@ -38,6 +42,64 @@ impl<'a> BitmapIterator<'a> {
3842
fn advance(&mut self) -> bool {
3943
unsafe { ffi::roaring_advance_uint32_iterator(&mut self.iterator) }
4044
}
45+
46+
/// Attempt to read many values from the iterator into `dst`
47+
///
48+
/// Returns the number of items read from the iterator, may be `< dst.len()` iff
49+
/// the iterator is exhausted.
50+
///
51+
/// This can be much more efficient than repeated iteration.
52+
///
53+
/// # Examples
54+
///
55+
/// ```
56+
/// use croaring::Bitmap;
57+
///
58+
/// let mut bitmap: Bitmap = Bitmap::create();
59+
/// bitmap.add_range(0..100);
60+
/// bitmap.add(222);
61+
/// bitmap.add(555);
62+
///
63+
/// let mut buf = [0; 100];
64+
/// let mut iter = bitmap.iter();
65+
/// assert_eq!(iter.next_many(&mut buf), 100);
66+
/// // Get the first 100 items, from the original range added
67+
/// for (i, item) in buf.iter().enumerate() {
68+
/// assert_eq!(*item, i as u32);
69+
/// }
70+
/// // Calls to next_many() can be interleaved with calls to next()
71+
/// assert_eq!(iter.next(), Some(222));
72+
/// assert_eq!(iter.next_many(&mut buf), 1);
73+
/// assert_eq!(buf[0], 555);
74+
///
75+
/// assert_eq!(iter.next(), None);
76+
/// assert_eq!(iter.next_many(&mut buf), 0);
77+
/// ```
78+
///
79+
/// ```
80+
/// use croaring::Bitmap;
81+
///
82+
/// fn print_by_chunks(bitmap: &Bitmap) {
83+
/// let mut buf = [0; 1024];
84+
/// let mut iter = bitmap.iter();
85+
/// loop {
86+
/// let n = iter.next_many(&mut buf);
87+
/// if n == 0 {
88+
/// break;
89+
/// }
90+
/// println!("{:?}", &buf[..n]);
91+
/// }
92+
/// }
93+
///
94+
/// # print_by_chunks(&Bitmap::of(&[1, 2, 8, 20, 1000]));
95+
/// ```
96+
#[inline]
97+
pub fn next_many(&mut self, dst: &mut [u32]) -> usize {
98+
let count: u32 = u32::try_from(dst.len()).unwrap_or(u32::MAX);
99+
let result = unsafe { ffi::roaring_read_uint32_iterator(&mut self.iterator, dst.as_mut_ptr(), count)};
100+
debug_assert!(result <= count);
101+
result as usize
102+
}
41103
}
42104

43105
impl<'a> Iterator for BitmapIterator<'a> {

croaring/src/treemap/imp.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -564,13 +564,21 @@ impl Treemap {
564564
pub fn to_vec(&self) -> Vec<u64> {
565565
let treemap_size: usize = self.cardinality().try_into().unwrap();
566566

567-
let mut buffer: Vec<u64> = Vec::with_capacity(treemap_size);
568-
569-
for (key, bitmap) in &self.map {
570-
bitmap.iter().for_each(|bit| buffer.push(util::join(*key, bit)));
567+
let mut result: Vec<u64> = Vec::with_capacity(treemap_size);
568+
let mut buffer = [0; 1024];
569+
570+
for (&key, bitmap) in &self.map {
571+
let mut iter = bitmap.iter();
572+
loop {
573+
let n = iter.next_many(&mut buffer);
574+
if n == 0 {
575+
break;
576+
}
577+
result.extend(buffer[..n].iter().map(|&bit| util::join(key, bit)))
578+
}
571579
}
572580

573-
buffer
581+
result
574582
}
575583

576584
/// Creates a new treemap from a slice of u64 integers

0 commit comments

Comments
 (0)