Skip to content

Commit

Permalink
Some slight performance improvements to block window (#30)
Browse files Browse the repository at this point in the history
* Use with_capacity since the window will almost always reach exactly this size

* fmt

* Rename + use parent gd data and save a call to the store
  • Loading branch information
michaelsutton authored Sep 1, 2022
1 parent 2e3db34 commit 46094d7
Showing 1 changed file with 33 additions and 31 deletions.
64 changes: 33 additions & 31 deletions consensus/src/processes/dagtraversalmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ impl<T: GhostdagStoreReader, U: BlockWindowCacheReader> DagTraversalManager<T, U
}
}
pub fn block_window(&self, high_ghostdag_data: Arc<GhostdagData>, window_size: usize) -> BlockWindowHeap {
let mut window_heap = SizedUpBlockHeap::new(self.ghostdag_store.clone(), window_size);
if window_size == 0 {
return window_heap.binary_heap;
return BlockWindowHeap::new();
}

let mut current_gd = high_ghostdag_data;
Expand All @@ -53,50 +52,59 @@ impl<T: GhostdagStoreReader, U: BlockWindowCacheReader> DagTraversalManager<T, U

if let Some(cache) = cache {
if let Some(selected_parent_binary_heap) = cache.get(&current_gd.selected_parent) {
let mut window_heap = SizedUpBlockHeap::from_binary_heap(
self.ghostdag_store.clone(),
window_size,
(*selected_parent_binary_heap).clone(),
);
let mut window_heap =
BoundedSizeBlockHeap::from_binary_heap(window_size, (*selected_parent_binary_heap).clone());
if current_gd.selected_parent != self.genesis_hash {
self.try_push_mergeset(&mut window_heap, &current_gd);
self.try_push_mergeset(
&mut window_heap,
&current_gd,
self.ghostdag_store
.get_blue_work(current_gd.selected_parent)
.unwrap(),
);
}

return window_heap.binary_heap;
}
}

let mut window_heap = BoundedSizeBlockHeap::new(window_size);

// Walk down the chain until we finish
loop {
assert!(!current_gd.selected_parent.is_origin(), "Block window should never get to the origin block");
assert!(!current_gd.selected_parent.is_origin(), "block window should never get to the origin block");
if current_gd.selected_parent == self.genesis_hash {
break;
}

let done = self.try_push_mergeset(&mut window_heap, &current_gd);
if done {
break;
}

current_gd = self
let parent_gd = self
.ghostdag_store
.get_data(current_gd.selected_parent)
.unwrap();
let selected_parent_blue_work_too_low =
self.try_push_mergeset(&mut window_heap, &current_gd, parent_gd.blue_work);
// No need to further iterate since past of selected parent has even lower blue work
if selected_parent_blue_work_too_low {
break;
}
current_gd = parent_gd;
}

window_heap.binary_heap
}

fn try_push_mergeset(&self, heap: &mut SizedUpBlockHeap<T>, ghostdag_data: &GhostdagData) -> bool {
fn try_push_mergeset(
&self, heap: &mut BoundedSizeBlockHeap, ghostdag_data: &GhostdagData, selected_parent_blue_work: BlueWorkType,
) -> bool {
// If the window is full and the selected parent is less than the minimum then we break
// because this means that there cannot be any more blocks in the past with higher blue work
if !heap.try_push(ghostdag_data.selected_parent) {
if !heap.try_push(ghostdag_data.selected_parent, selected_parent_blue_work) {
return true;
}

for block in ghostdag_data.descending_mergeset_without_selected_parent(self.ghostdag_store.deref()) {
// If it's smaller than minimum then we won't be able to add the rest because we iterate in descending blue work order.
if !heap.try_push_with_blue_work(block.hash, block.blue_work) {
if !heap.try_push(block.hash, block.blue_work) {
break;
}
}
Expand All @@ -105,27 +113,21 @@ impl<T: GhostdagStoreReader, U: BlockWindowCacheReader> DagTraversalManager<T, U
}
}

struct SizedUpBlockHeap<T: GhostdagStoreReader> {
struct BoundedSizeBlockHeap {
binary_heap: BlockWindowHeap,
ghostdag_store: Arc<T>,
size: usize,
}

impl<T: GhostdagStoreReader> SizedUpBlockHeap<T> {
fn new(ghostdag_store: Arc<T>, size: usize) -> Self {
Self::from_binary_heap(ghostdag_store, size, BinaryHeap::new())
}

fn from_binary_heap(ghostdag_store: Arc<T>, size: usize, binary_heap: BlockWindowHeap) -> Self {
Self { ghostdag_store, size, binary_heap }
impl BoundedSizeBlockHeap {
fn new(size: usize) -> Self {
Self::from_binary_heap(size, BinaryHeap::with_capacity(size))
}

fn try_push(&mut self, hash: Hash) -> bool {
let blue_work = self.ghostdag_store.get_blue_work(hash).unwrap();
self.try_push_with_blue_work(hash, blue_work)
fn from_binary_heap(size: usize, binary_heap: BlockWindowHeap) -> Self {
Self { size, binary_heap }
}

fn try_push_with_blue_work(&mut self, hash: Hash, blue_work: BlueWorkType) -> bool {
fn try_push(&mut self, hash: Hash, blue_work: BlueWorkType) -> bool {
let r_sortable_block = Reverse(SortableBlock { hash, blue_work });
if self.binary_heap.len() == self.size {
if let Some(max) = self.binary_heap.peek() {
Expand Down

0 comments on commit 46094d7

Please sign in to comment.