Skip to content

Commit

Permalink
Improve memory use by shrinking arrays during operations
Browse files Browse the repository at this point in the history
  • Loading branch information
Firstyear committed May 30, 2024
1 parent 55342a1 commit f22bf6f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 16 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.4"
version = "0.2.5"
authors = ["William Brown <[email protected]>"]
edition = "2021"

Expand Down
6 changes: 3 additions & 3 deletions src/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl IDLBitRange {
let r = self.list.binary_search(&candidate);
match r {
Ok(idx) => {
let mut existing = self.list.get_mut(idx).unwrap();
let existing = self.list.get_mut(idx).unwrap();
existing.mask |= candidate.mask;
}
Err(idx) => {
Expand All @@ -227,7 +227,7 @@ impl IDLBitRange {
//
// To do this, we not the candidate, so all other bits remain,
// then we perform and &= so that the existing bits survive.
let mut existing = self.list.get_mut(idx).unwrap();
let existing = self.list.get_mut(idx).unwrap();

existing.mask &= !candidate.mask;

Expand All @@ -252,7 +252,7 @@ impl IDLBitRange {

// Get the highest IDLRange out:
if let Some(last) = self.list.last_mut() {
if (*last).range == range {
if last.range == range {
// Insert the bit.
(*last).push_id(bvalue);
return;
Expand Down
60 changes: 48 additions & 12 deletions src/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ enum IDLState {
}

impl IDLState {
fn shrink_to_fit(&mut self) {
match self {
IDLState::Sparse(svec) => svec.shrink_to_fit(),
IDLState::Compressed(vec) => vec.shrink_to_fit(),
}
}

fn sparse_bitand_fast_path(smol: &[u64], lrg: &[u64]) -> Self {
let mut nlist = SmallVec::with_capacity(smol.len());
// We cache the idx inbetween to narrow the bst sizes.
Expand All @@ -99,6 +106,8 @@ impl IDLState {
idx_min = idx;
}
});

nlist.shrink_to_fit();
IDLState::Sparse(nlist)
}

Expand All @@ -120,6 +129,7 @@ impl IDLState {
}
});

nlist.shrink_to_fit();
IDLState::Sparse(nlist)
}
}
Expand Down Expand Up @@ -201,7 +211,7 @@ impl Default for IDLBitRange {
/// Construct a new, empty set.
fn default() -> Self {
IDLBitRange {
state: IDLState::Sparse(SmallVec::new()),
state: IDLState::Sparse(SmallVec::with_capacity(0)),
}
}
}
Expand Down Expand Up @@ -334,8 +344,8 @@ impl IDLBitRange {
let range: u64 = id - bvalue;

if let Some(last) = list.last_mut() {
debug_assert!(id >= (*last).range);
if (*last).range == range {
debug_assert!(id >= last.range);
if last.range == range {
// Insert the bit.
(*last).push_id(bvalue);
return;
Expand Down Expand Up @@ -366,7 +376,7 @@ impl IDLBitRange {
let r = list.binary_search(&candidate);
match r {
Ok(idx) => {
let mut existing = list.get_mut(idx).unwrap();
let existing = list.get_mut(idx).unwrap();
existing.mask |= candidate.mask;
}
Err(idx) => {
Expand Down Expand Up @@ -402,7 +412,7 @@ impl IDLBitRange {
//
// To do this, we not the candidate, so all other bits remain,
// then we perform and &= so that the existing bits survive.
let mut existing = list.get_mut(idx).unwrap();
let existing = list.get_mut(idx).unwrap();

existing.mask &= !candidate.mask;

Expand All @@ -422,7 +432,7 @@ impl IDLBitRange {
if self.is_compressed() {
return;
}
let mut prev_state = IDLState::Compressed(Vec::new());
let mut prev_state = IDLState::Compressed(Vec::with_capacity(0));
std::mem::swap(&mut prev_state, &mut self.state);
match prev_state {
IDLState::Sparse(list) => list.into_iter().for_each(|i| unsafe {
Expand All @@ -441,14 +451,15 @@ impl IDLBitRange {
None
} else {
let mut maybe = IDLBitRange {
state: IDLState::Compressed(Vec::new()),
state: IDLState::Compressed(Vec::with_capacity(0)),
};
list.iter().for_each(|id| unsafe { maybe.push_id(*id) });

if maybe.len_ranges() > 0
&& (maybe.len() / maybe.len_ranges()) >= AVG_RANGE_COMP_REQ
{
let IDLBitRange { state } = maybe;
let IDLBitRange { mut state } = maybe;
state.shrink_to_fit();
Some(state)
} else {
None
Expand Down Expand Up @@ -507,6 +518,9 @@ impl IDLBitRange {
}
}
}

nlist.shrink_to_fit();

IDLState::Sparse(nlist)
};

Expand Down Expand Up @@ -540,12 +554,14 @@ impl IDLBitRange {
}
});

nlist.shrink_to_fit();

IDLBitRange {
state: IDLState::Sparse(nlist),
}
}
(IDLState::Compressed(list1), IDLState::Compressed(list2)) => {
let mut nlist = Vec::new();
let mut nlist = Vec::with_capacity(0);
let mut liter = list1.iter();
let mut riter = list2.iter();

Expand Down Expand Up @@ -577,6 +593,7 @@ impl IDLBitRange {
if nlist.is_empty() {
IDLBitRange::new()
} else {
nlist.shrink_to_fit();
IDLBitRange {
state: IDLState::Compressed(nlist),
}
Expand Down Expand Up @@ -636,6 +653,8 @@ impl IDLBitRange {
rnext = riter.next();
}

nlist.shrink_to_fit();

IDLState::Sparse(nlist)
};

Expand Down Expand Up @@ -672,7 +691,7 @@ impl IDLBitRange {
Ok(idx) => {
debug_assert!(Ok(idx + idx_min) == list.binary_search(&candidate));
let idx = idx + idx_min;
let mut existing = list.get_mut(idx).unwrap();
let existing = list.get_mut(idx).unwrap();
existing.mask |= candidate.mask;
debug_assert!(idx >= idx_min);
idx_min = idx;
Expand All @@ -689,6 +708,8 @@ impl IDLBitRange {
};
});

list.shrink_to_fit();

IDLBitRange {
state: IDLState::Compressed(list),
}
Expand Down Expand Up @@ -743,6 +764,9 @@ impl IDLBitRange {
nlist.push(newrange);
rnextrange = riter.next();
}

nlist.shrink_to_fit();

IDLBitRange {
state: IDLState::Compressed(nlist),
}
Expand Down Expand Up @@ -788,6 +812,8 @@ impl IDLBitRange {
lnext = liter.next();
}

nlist.shrink_to_fit();

IDLBitRange {
state: IDLState::Sparse(nlist),
}
Expand Down Expand Up @@ -832,6 +858,8 @@ impl IDLBitRange {
}
});

nlist.shrink_to_fit();

IDLBitRange {
state: IDLState::Sparse(nlist),
}
Expand All @@ -850,7 +878,7 @@ impl IDLBitRange {
if let Ok(idx) = partition.binary_search(&candidate) {
debug_assert!(Ok(idx + idx_min) == nlist.binary_search(&candidate));
let idx = idx + idx_min;
let mut existing = nlist.get_mut(idx).unwrap();
let existing = nlist.get_mut(idx).unwrap();
existing.mask &= !candidate.mask;
if existing.mask == 0 {
nlist.remove(idx);
Expand All @@ -859,6 +887,9 @@ impl IDLBitRange {
idx_min = idx;
}
});

nlist.shrink_to_fit();

IDLBitRange {
state: IDLState::Compressed(nlist),
}
Expand Down Expand Up @@ -908,6 +939,8 @@ impl IDLBitRange {
lnextrange = liter.next();
}

nlist.shrink_to_fit();

IDLBitRange {
state: IDLState::Compressed(nlist),
}
Expand Down Expand Up @@ -943,7 +976,10 @@ impl FromIterator<u64> for IDLBitRange {
}
});

new_sparse.maybe_compress();
if !new_sparse.maybe_compress() {
// If the compression didn't occur, trim the vec anyway.
new_sparse.state.shrink_to_fit();
}
new_sparse
}
}
Expand Down

0 comments on commit f22bf6f

Please sign in to comment.