Skip to content

Commit

Permalink
Breaking Changes to be idiomatic #115
Browse files Browse the repository at this point in the history
See #108 for some justification of why we're making breaking changes

### Update constructors with idiomatic names

Rename `::create` to `::new`, and `::create_with_capacity` to `::with_container_capacity`

Idiomatic rust uses `StructName::new()` as the default construction function, and functions to create with configuration are named like `StructName::with_x(x)` (see e.g. `Vec::new()` and `Vec::with_capacity()`

### Add a `From` impl for `&[u32]` and `[u32; N]`

Still leave `Bitmap::of`: There are type inference difficulties with `Bitmap::from(&[1, 2, 3])` (because the type is inferred to `&[i32]`) or `Bitmap::from(&vec)` (because `From<&Vec<u32>>` isn't implemented)

### Add some benchmarks for the ways of batch-constructing a bitmap

Some benchmarks for adding individually, vs from an iterator, etc.

### Implement FromIterator/Extend in terms of `add_bulk`

It can be a pretty big waste of memory to collect into a Vec in order to construct from an iterator, and it's only a tiny bit faster.
  • Loading branch information
Dr-Emann authored Aug 7, 2023
2 parents 6b82631 + 517b9a0 commit 03d2707
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 184 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The original java version can be found at https://github.com/RoaringBitmap/Roari
```rust
use croaring::Bitmap;

let mut rb1 = Bitmap::create();
let mut rb1 = Bitmap::new();
rb1.add(1);
rb1.add(2);
rb1.add(3);
Expand All @@ -18,13 +18,13 @@ rb1.add(100);
rb1.add(1000);
rb1.run_optimize();

let mut rb2 = Bitmap::create();
let mut rb2 = Bitmap::new();
rb2.add(3);
rb2.add(4);
rb2.add(1000);
rb2.run_optimize();

let mut rb3 = Bitmap::create();
let mut rb3 = Bitmap::new();

assert_eq!(rb1.cardinality(), 7);
assert!(rb1.contains(3));
Expand Down Expand Up @@ -63,15 +63,15 @@ For 64bit Bitmap support, checkout the [`Treemap`](https://docs.rs/croaring/0.4.
use std::u64;
use croaring::Treemap;

let mut treemap = Treemap::create();
let mut treemap = Treemap::new();
treemap.add(u64::MAX);
treemap.remove(u64::MAX);

/// Serialization compatible with croaring Treemap version at https://github.com/RoaringBitmap/CRoaring/blob/b88b002407b42fafaea23ea5009a54a24d1c1ed4/cpp/roaring64map.hh

use croaring::treemap::NativeSerializer;

let mut treemap1 = Treemap::create();
let mut treemap1 = Treemap::new();

for i in 100..1000 {
treemap1.add(i);
Expand All @@ -83,7 +83,7 @@ treemap1.add(std::u64::MAX);
/// Serialization compatible with JVM Treemap version at https://github.com/RoaringBitmap/RoaringBitmap/blob/34654b2d5c3e75e7f9bca1672f4c0b5800d60cf3/roaringbitmap/src/main/java/org/roaringbitmap/longlong/Roaring64NavigableMap.java
use croaring::treemap::JvmSerializer;

let mut treemap2 = Treemap::create();
let mut treemap2 = Treemap::new();

for i in 100..1000 {
treemap2.add(i);
Expand Down
96 changes: 83 additions & 13 deletions croaring/benches/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ use criterion::{

use croaring::{Bitmap, Portable};

fn create(c: &mut Criterion) {
c.bench_function("create", |b| b.iter(Bitmap::create));
fn new(c: &mut Criterion) {
c.bench_function("new", |b| b.iter(Bitmap::new));

c.bench_function("create_with_capacity", |b| {
b.iter(|| Bitmap::create_with_capacity(10000))
c.bench_function("with_capacity", |b| {
b.iter(|| Bitmap::with_container_capacity(10_000))
});
}

fn add(c: &mut Criterion) {
c.bench_function("add", |b| {
let mut bitmap = Bitmap::create();
let mut bitmap = Bitmap::new();

b.iter(|| bitmap.add(10000));
});
}

fn add_many(c: &mut Criterion) {
c.bench_function("add_many", |b| {
let mut bitmap = Bitmap::create();
let mut bitmap = Bitmap::new();
let int_slice = &[10, 100, 10_000, 1_000_000, 10_000_000];

b.iter(|| bitmap.add_many(black_box(int_slice)));
Expand All @@ -31,7 +31,7 @@ fn add_many(c: &mut Criterion) {

fn remove(c: &mut Criterion) {
c.bench_function("remove", |b| {
let mut bitmap = Bitmap::create();
let mut bitmap = Bitmap::new();

b.iter(|| bitmap.remove(10000));
});
Expand All @@ -40,15 +40,15 @@ fn remove(c: &mut Criterion) {
fn contains(c: &mut Criterion) {
let mut group = c.benchmark_group("contains");
group.bench_function("true", |b| {
let mut bitmap = Bitmap::create();
let mut bitmap = Bitmap::new();

bitmap.add(5);

b.iter(|| bitmap.contains(5));
});

group.bench_function("false", |b| {
let bitmap = Bitmap::create();
let bitmap = Bitmap::new();

b.iter(|| bitmap.contains(5));
});
Expand All @@ -67,8 +67,8 @@ fn cardinality(c: &mut Criterion) {
}

fn binops(c: &mut Criterion) {
let bitmap1 = Bitmap::of(&[500, 1000]);
let bitmap2 = Bitmap::of(&[1000, 2000]);
let bitmap1 = Bitmap::from([500, 1000]);
let bitmap2 = Bitmap::from([1000, 2000]);

macro_rules! bench_op {
($new:ident, $inplace:ident) => {{
Expand Down Expand Up @@ -146,7 +146,7 @@ fn get_serialized_size_in_bytes(c: &mut Criterion) {
fn is_empty(c: &mut Criterion) {
let mut group = c.benchmark_group("is_empty");
group.bench_function("true", |b| {
let bitmap = Bitmap::create();
let bitmap = Bitmap::new();
b.iter(|| bitmap.is_empty());
});
group.bench_function("false", |b| {
Expand Down Expand Up @@ -184,9 +184,77 @@ fn deserialize(c: &mut Criterion) {
}
}

fn bulk_new(c: &mut Criterion) {
const N: u32 = 1_000_000;

let mut group = c.benchmark_group("bulk_new");
group.throughput(Throughput::Elements(N.into()));
let range = black_box(0..N);
group.bench_function("range_new", |b| {
b.iter(|| Bitmap::from_range(range.clone()));
});
group.bench_function("collect", |b| {
b.iter(|| Bitmap::from_iter(range.clone()));
});
group.bench_function("slice_init", |b| {
let bulk_data = black_box(range.clone().collect::<Vec<_>>());
b.iter(|| Bitmap::of(&bulk_data));
});
group.bench_function("sequential_adds", |b| {
b.iter(|| {
let mut bitmap = Bitmap::new();
for i in range.clone() {
bitmap.add(i);
}
bitmap
});
});

group.finish();
}

fn random_iter(c: &mut Criterion) {
const N: u32 = 5_000;
// Clamp values so we get some re-use of containers
const MAX: u32 = 8 * (u16::MAX as u32 + 1);

let mut group = c.benchmark_group("random_iter");
group.throughput(Throughput::Elements(N.into()));

let rand_iter = {
const MULTIPLIER: u32 = 742938285;
const MODULUS: u32 = (1 << 31) - 1;
// Super simple LCG iterator
let mut z = 20170705; // seed
std::iter::from_fn(move || {
z = (MULTIPLIER * z) % MODULUS;
Some(z % MAX)
})
};

group.bench_function("random_adds", |b| {
b.iter(|| {
let mut bitmap = Bitmap::new();
rand_iter.clone().take(N as usize).for_each(|item| {
bitmap.add(item);
});
bitmap
});
});
group.bench_function("random_from_iter", |b| {
b.iter(|| Bitmap::from_iter(rand_iter.clone().take(N as usize)));
});
group.bench_function("collect_to_vec_first", |b| {
b.iter(|| {
let vec = rand_iter.clone().take(N as usize).collect::<Vec<_>>();
Bitmap::of(&vec)
});
});
}

criterion_group!(
benches,
create,
new,
add,
add_many,
remove,
Expand All @@ -200,5 +268,7 @@ criterion_group!(
of,
serialize,
deserialize,
bulk_new,
random_iter,
);
criterion_main!(benches);
14 changes: 7 additions & 7 deletions croaring/benches/performance_comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ fn roaring_bitmap_of(items: &[u32]) -> RoaringBitmap {
items.iter().copied().collect()
}

fn create(c: &mut Criterion) {
fn new(c: &mut Criterion) {
compare(
&mut c.benchmark_group("create"),
&mut c.benchmark_group("new"),
|| (),
|| (),
|()| Bitmap::create(),
|()| Bitmap::new(),
|()| RoaringBitmap::new(),
);
}
Expand All @@ -47,7 +47,7 @@ fn create_and_add_one(c: &mut Criterion) {
|| (),
|| (),
|()| {
let mut bitmap = Bitmap::create();
let mut bitmap = Bitmap::new();
bitmap.add(black_box(1));
bitmap
},
Expand All @@ -65,7 +65,7 @@ fn add(c: &mut Criterion) {
let mut group = c.benchmark_group("add_several");
compare(
&mut group,
Bitmap::create,
Bitmap::new,
RoaringBitmap::new,
|mut bitmap: Bitmap| {
for &item in SIMPLE_ITEMS {
Expand All @@ -82,7 +82,7 @@ fn add(c: &mut Criterion) {
);
group.bench_function("croaring many", |b| {
b.iter_batched(
Bitmap::create,
Bitmap::new,
|mut bitmap| {
bitmap.add_many(black_box(SIMPLE_ITEMS));
bitmap
Expand Down Expand Up @@ -201,7 +201,7 @@ fn iter(c: &mut Criterion) {

criterion_group!(
benches,
create,
new,
create_and_add_one,
add,
remove,
Expand Down
Loading

0 comments on commit 03d2707

Please sign in to comment.