This commit is contained in:
2018-02-06 11:16:42 +01:00
parent 96720c83e7
commit a62326cdb3
4 changed files with 94 additions and 12 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,3 @@
/target/ /target/
Cargo.lock Cargo.lock
/.criterion/

View File

@@ -4,12 +4,13 @@ version = "0.1.0"
authors = ["logaritmisk <anders.e.olsson@gmail.com>"] authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
[dependencies] [dependencies]
ordermap = "0.4"
rayon = "0.9" rayon = "0.9"
serde = "1.0" serde = "1.0"
unreachable = "1.0" unreachable = "1.0"
[dev-dependencies] [dev-dependencies]
criterion = "0.1" criterion = "0.2"
rand = "0.4" rand = "0.4"
serde_test = "1.0" serde_test = "1.0"

View File

@@ -11,7 +11,7 @@ use rand::{Rng, SeedableRng, XorShiftRng};
use bit_set::BitSet; use bit_set::BitSet;
fn default_set<C: FromIterator<u64>>(n: usize) -> C { fn random<C: FromIterator<u64>>(n: usize) -> C {
let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]); let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
(0..n).map(|_| rng.next_u64()).collect() (0..n).map(|_| rng.next_u64()).collect()
@@ -33,20 +33,77 @@ fn insert(data: &[u64]) {
} }
} }
fn sub(a: &BitSet, b: &BitSet) { fn iter(set: &BitSet) {
set.iter().collect::<Vec<_>>();
}
fn is_subset(a: &BitSet, b: &BitSet) {
a.is_subset(b);
}
fn ops_bit_or(a: &BitSet, b: &BitSet) {
a | b;
}
fn ops_sub(a: &BitSet, b: &BitSet) {
a - b; a - b;
} }
fn criterion_benchmark(c: &mut Criterion) { fn criterion_benchmark(c: &mut Criterion) {
let data: Vec<_> = default_set(1000); // c.sample_size(200);
c.bench_function("contains", |b| b.iter(|| contains(&data))); c.bench_function("contains", move |b| {
c.bench_function("insert", |b| b.iter(|| insert(&data))); let data: Vec<_> = random(10_000);
let lhs: BitSet = default_set(1000); b.iter(|| contains(&data));
let rhs: BitSet = default_set(1000); });
c.bench_function("sub", |b| b.iter(|| sub(&lhs, &rhs))); c.bench_function("insert", move |b| {
let data: Vec<_> = random(10_000);
b.iter(|| insert(&data));
});
c.bench_function("iter", move |b| {
let set: BitSet = random(10_000);
b.iter(|| iter(&set));
});
c.bench_function("is_subset (>)", |b| {
let lhs: BitSet = random(10_000);
let rhs: BitSet = random(5_000);
b.iter(|| is_subset(&lhs, &rhs));
});
c.bench_function("is_subset (<)", |b| {
let lhs: BitSet = random(5_000);
let rhs: BitSet = random(10_000);
b.iter(|| is_subset(&lhs, &rhs));
});
c.bench_function("is_subset (=)", |b| {
let lhs: BitSet = random(10_000);
let rhs: BitSet = random(10_000);
b.iter(|| is_subset(&lhs, &rhs));
});
c.bench_function("ops_bit_or", move |b| {
let lhs: BitSet = random(10_000);
let rhs: BitSet = random(10_000);
b.iter(|| ops_bit_or(&lhs, &rhs));
});
c.bench_function("ops_sub", move |b| {
let lhs: BitSet = random(10_000);
let rhs: BitSet = random(10_000);
b.iter(|| ops_sub(&lhs, &rhs));
});
} }
criterion_group!(benches, criterion_benchmark); criterion_group!(benches, criterion_benchmark);

View File

@@ -1,3 +1,4 @@
extern crate ordermap;
extern crate rayon; extern crate rayon;
extern crate serde; extern crate serde;
extern crate unreachable; extern crate unreachable;
@@ -8,6 +9,7 @@ use std::iter::{FromIterator, IntoIterator, Iterator};
use std::default::Default; use std::default::Default;
use std::collections::{HashMap, LinkedList}; use std::collections::{HashMap, LinkedList};
use ordermap::OrderMap;
use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -22,6 +24,7 @@ const BITS: u64 = 64;
type Block = u64; type Block = u64;
type Storage = HashMap<u64, Block, BitBuildHasher>; type Storage = HashMap<u64, Block, BitBuildHasher>;
// type Storage = OrderMap<u64, Block, BitBuildHasher>;
pub type BitHashMap<V> = HashMap<u64, V, BitBuildHasher>; pub type BitHashMap<V> = HashMap<u64, V, BitBuildHasher>;
@@ -64,7 +67,7 @@ impl BitSet {
pub fn shrink_to_fit(&mut self) { pub fn shrink_to_fit(&mut self) {
self.blocks.retain(|_, block| *block != 0); self.blocks.retain(|_, block| *block != 0);
self.blocks.shrink_to_fit() // self.blocks.shrink_to_fit();
} }
pub fn iter(&self) -> Iter { pub fn iter(&self) -> Iter {
@@ -246,6 +249,27 @@ impl<'a> ops::BitOr<&'a Self> for BitSet {
} }
} }
impl<'a> ops::BitOr<&'a BitSet> for &'a BitSet {
type Output = BitSet;
#[inline]
fn bitor(self, rhs: &'a BitSet) -> BitSet {
let mut set = self.clone();
for (key, value) in &rhs.blocks {
let block = set.blocks.entry(*key).or_insert(0);
let n = block.count_ones();
*block |= value;
set.nbits += (block.count_ones() - n) as usize;
}
set
}
}
impl<'a> ops::Sub<&'a BitSet> for &'a BitSet { impl<'a> ops::Sub<&'a BitSet> for &'a BitSet {
type Output = BitSet; type Output = BitSet;
@@ -269,6 +293,7 @@ impl<'a> ops::Sub<&'a BitSet> for &'a BitSet {
pub struct Iter<'a> { pub struct Iter<'a> {
iter: std::collections::hash_map::Iter<'a, u64, u64>, iter: std::collections::hash_map::Iter<'a, u64, u64>,
// iter: ordermap::Iter<'a, u64, u64>,
block: u64, block: u64,
bits: u64, bits: u64,
bit: u64, bit: u64,
@@ -276,6 +301,7 @@ pub struct Iter<'a> {
pub struct IntoIter { pub struct IntoIter {
iter: std::collections::hash_map::IntoIter<u64, u64>, iter: std::collections::hash_map::IntoIter<u64, u64>,
// iter: ordermap::IntoIter<u64, u64>,
block: u64, block: u64,
bits: u64, bits: u64,
bit: u64, bit: u64,