Skip to content

Commit

Permalink
Improve fast path handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Firstyear committed Mar 4, 2022
1 parent 078bf04 commit 32fb786
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "idlset"
version = "0.2.2"
version = "0.2.3"
authors = ["William Brown <[email protected]>"]
edition = "2021"

Expand Down
32 changes: 20 additions & 12 deletions src/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const AVG_RANGE_COMP_REQ: usize = 12;
const AVG_RANGE_COMP_REQ: usize = 5;

const FAST_PATH_BST_RATIO: usize = 8;
const FAST_PATH_BST_SIZE: usize = 8;

/// The core representation of sets of integers in compressed format.
#[derive(Serialize, Deserialize, Clone)]
Expand Down Expand Up @@ -83,7 +82,7 @@ enum IDLState {

impl IDLState {
fn sparse_bitand_fast_path(smol: &[u64], lrg: &[u64]) -> Self {
let mut nlist = SmallVec::new();
let mut nlist = SmallVec::with_capacity(smol.len());
// We cache the idx inbetween to narrow the bst sizes.
let mut idx_min = 0;
smol.iter().for_each(|id| {
Expand Down Expand Up @@ -458,15 +457,19 @@ impl IDLBitRange {
fn bitand_inner(&self, rhs: &Self) -> Self {
match (&self.state, &rhs.state) {
(IDLState::Sparse(lhs), IDLState::Sparse(rhs)) => {
// Fast path if there is a large difference in the sizes.
let state = if (rhs.len() + lhs.len() <= FAST_PATH_BST_SIZE)
|| (!lhs.is_empty() && (rhs.len() / lhs.len()) >= FAST_PATH_BST_RATIO)
{
// Fast path if there is a really large difference in the sizes.
let state = if !lhs.is_empty() && (rhs.len() / lhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitand_fast_path(lhs.as_slice(), rhs.as_slice())
} else if !rhs.is_empty() && (lhs.len() / rhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitand_fast_path(rhs.as_slice(), lhs.as_slice())
} else {
let mut nlist = SmallVec::new();
let x = if rhs.len() > lhs.len() {
rhs.len()
} else {
lhs.len()
};

let mut nlist = SmallVec::with_capacity(x);

let mut liter = lhs.iter();
let mut riter = rhs.iter();
Expand Down Expand Up @@ -502,7 +505,7 @@ impl IDLBitRange {
// Could be be better to decompress instead? This currently
// assumes sparse is MUCH smaller than compressed ...

let mut nlist = SmallVec::new();
let mut nlist = SmallVec::with_capacity(sparselist.len());
let mut idx_min = 0;

sparselist.iter().for_each(|id| {
Expand Down Expand Up @@ -575,9 +578,7 @@ impl IDLBitRange {
match (&self.state, &rhs.state) {
(IDLState::Sparse(lhs), IDLState::Sparse(rhs)) => {
// If one is much smaller, we can clone the larger and just insert.
let state = if (rhs.len() + lhs.len() <= FAST_PATH_BST_SIZE)
|| (!lhs.is_empty() && (rhs.len() / lhs.len()) >= FAST_PATH_BST_RATIO)
{
let state = if !lhs.is_empty() && (rhs.len() / lhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitor_fast_path(lhs.as_slice(), rhs.as_slice())
} else if !rhs.is_empty() && (lhs.len() / rhs.len()) >= FAST_PATH_BST_RATIO {
IDLState::sparse_bitor_fast_path(rhs.as_slice(), lhs.as_slice())
Expand Down Expand Up @@ -741,7 +742,7 @@ impl IDLBitRange {
fn bitandnot_inner(&self, rhs: &Self) -> Self {
match (&self.state, &rhs.state) {
(IDLState::Sparse(lhs), IDLState::Sparse(rhs)) => {
let mut nlist = SmallVec::new();
let mut nlist = SmallVec::with_capacity(lhs.len());

let mut liter = lhs.iter();
let mut riter = rhs.iter();
Expand Down Expand Up @@ -1196,6 +1197,7 @@ impl<'a> IntoIterator for &'a IDLBitRange {
#[cfg(test)]
mod tests {
use super::IDLBitRange;
use super::IDLState;
use super::AVG_RANGE_COMP_REQ;
use crate::AndNot;
use std::iter::FromIterator;
Expand Down Expand Up @@ -1781,4 +1783,10 @@ mod tests {
let idl_result = idl_a.andnot(idl_b);
assert_eq!(idl_result, idl_expect);
}

#[test]
fn test_sizeof_idlstate() {
let sz = std::mem::size_of::<IDLState>();
eprintln!("{}", sz);
}
}

0 comments on commit 32fb786

Please sign in to comment.