Retire pruned cache (#3573)

* use range beneath subtree for efficient is_pruned check
This commit is contained in:
Antioch Peverell
2021-02-23 19:34:32 +00:00
committed by GitHub
parent 08523b2b39
commit 57f4592499
4 changed files with 53 additions and 32 deletions
+3
View File
@@ -285,6 +285,9 @@ impl<T: PMMRable> PMMRBackend<T> {
}
fn is_compacted(&self, pos: u64) -> bool {
if self.leaf_set.includes(pos) {
return false;
}
self.is_pruned(pos) && !self.is_pruned_root(pos)
}
+20 -28
View File
@@ -25,8 +25,9 @@ use std::io::{self, Write};
use std::path::{Path, PathBuf};
use croaring::Bitmap;
use grin_core::core::pmmr;
use crate::core::core::pmmr::{bintree_postorder_height, family, path};
use crate::core::core::pmmr::{bintree_postorder_height, family};
use crate::{read_bitmap, save_via_temp_file};
/// Maintains a list of previously pruned nodes in PMMR, compacting the list as
@@ -44,8 +45,6 @@ pub struct PruneList {
path: Option<PathBuf>,
/// Bitmap representing pruned root node positions.
bitmap: Bitmap,
/// Bitmap representing all pruned node positions (everything under the pruned roots).
pruned_cache: Bitmap,
shift_cache: Vec<u64>,
leaf_shift_cache: Vec<u64>,
}
@@ -59,7 +58,6 @@ impl PruneList {
PruneList {
path,
bitmap,
pruned_cache: Bitmap::create(),
shift_cache: vec![],
leaf_shift_cache: vec![],
}
@@ -85,11 +83,10 @@ impl PruneList {
prune_list.init_caches();
if !prune_list.bitmap.is_empty() {
debug!("bitmap {} pos ({} bytes), pruned_cache {} pos ({} bytes), shift_cache {}, leaf_shift_cache {}",
debug!(
"bitmap {} pos ({} bytes), shift_cache {}, leaf_shift_cache {}",
prune_list.bitmap.cardinality(),
prune_list.bitmap.get_serialized_size_in_bytes(),
prune_list.pruned_cache.cardinality(),
prune_list.pruned_cache.get_serialized_size_in_bytes(),
prune_list.shift_cache.len(),
prune_list.leaf_shift_cache.len(),
);
@@ -102,7 +99,6 @@ impl PruneList {
pub fn init_caches(&mut self) {
self.build_shift_cache();
self.build_leaf_shift_cache();
self.build_pruned_cache();
}
/// Save the prune_list to disk.
@@ -232,16 +228,17 @@ impl PruneList {
pub fn add(&mut self, pos: u64) {
assert!(pos > 0, "prune list 1-indexed, 0 not valid pos");
if self.is_pruned(pos) {
return;
}
let mut current = pos;
loop {
let (parent, sibling) = family(current);
if self.bitmap.contains(sibling as u32) || self.pruned_cache.contains(sibling as u32) {
self.pruned_cache.add(current as u32);
if self.is_pruned_root(sibling) {
self.bitmap.remove(sibling as u32);
current = parent;
} else {
self.pruned_cache.add(current as u32);
self.bitmap.add(current as u32);
break;
}
@@ -263,26 +260,21 @@ impl PruneList {
self.bitmap.iter().map(|x| x as u64).collect()
}
/// Is the pos pruned?
/// Assumes the pruned_cache is fully built and up to date.
/// A pos is pruned if it is a pruned root directly or if it is
/// beneath the "next" pruned subtree.
/// We only need to consider the "next" subtree due to the append-only MMR structure.
pub fn is_pruned(&self, pos: u64) -> bool {
assert!(pos > 0, "prune list 1-indexed, 0 not valid pos");
self.pruned_cache.contains(pos as u32)
}
fn build_pruned_cache(&mut self) {
if self.bitmap.is_empty() {
return;
if self.is_pruned_root(pos) {
return true;
}
let maximum = self.bitmap.maximum().unwrap_or(0);
self.pruned_cache = Bitmap::create_with_capacity(maximum);
for pos in 1..(maximum + 1) {
let pruned = path(pos as u64, maximum as u64).any(|x| self.bitmap.contains(x as u32));
if pruned {
self.pruned_cache.add(pos as u32)
}
let rank = self.bitmap.rank(pos as u32);
if let Some(root) = self.bitmap.select(rank as u32) {
let range = pmmr::bintree_range(root as u64);
range.contains(&pos)
} else {
false
}
self.pruned_cache.run_optimize();
}
/// Is the specified position a root of a pruned subtree?