Skip to content

Commit 3c91a78

Browse files
authored
Merge pull request #6038 from kantai/perf/descendancy-check
Perf: descendancy check
2 parents cbb4fad + 9541920 commit 3c91a78

File tree

1 file changed

+59
-27
lines changed

1 file changed

+59
-27
lines changed

stackslib/src/chainstate/burn/db/sortdb.rs

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::collections::{HashMap, HashSet};
2020
use std::io::{ErrorKind, Write};
2121
use std::ops::{Deref, DerefMut};
2222
use std::str::FromStr;
23-
use std::sync::{Arc, LazyLock, Mutex};
23+
use std::sync::{Arc, LazyLock, Mutex, MutexGuard};
2424
use std::{cmp, fmt, fs};
2525

2626
use clarity::util::lru_cache::LruCache;
@@ -98,8 +98,9 @@ pub const REWARD_WINDOW_END: u64 = 144 * 90 + REWARD_WINDOW_START;
9898

9999
pub type BlockHeaderCache = HashMap<ConsensusHash, (Option<BlockHeaderHash>, ConsensusHash)>;
100100

101+
const DESCENDANCY_CACHE_SIZE: usize = 2000;
101102
static DESCENDANCY_CACHE: LazyLock<Arc<Mutex<LruCache<(SortitionId, BlockHeaderHash), bool>>>> =
102-
LazyLock::new(|| Arc::new(Mutex::new(LruCache::new(2000))));
103+
LazyLock::new(|| Arc::new(Mutex::new(LruCache::new(DESCENDANCY_CACHE_SIZE))));
103104

104105
pub enum FindIter<R> {
105106
Found(R),
@@ -1091,6 +1092,38 @@ pub trait SortitionHandle {
10911092
Ok(Some(StacksBlockId::new(&ch, &bhh)))
10921093
}
10931094

1095+
/// Check if the descendancy cache has an entry for whether or not the winning block in `key.0`
1096+
/// descends from `key.1`
1097+
///
1098+
/// If it does, return the cached entry
1099+
fn descendancy_cache_get(
1100+
cache: &mut MutexGuard<'_, LruCache<(SortitionId, BlockHeaderHash), bool>>,
1101+
key: &(SortitionId, BlockHeaderHash),
1102+
) -> Option<bool> {
1103+
match cache.get(key) {
1104+
Ok(result) => result,
1105+
// cache is broken, create a new one
1106+
Err(e) => {
1107+
error!("SortitionDB's descendant cache errored. Will continue operation with cleared cache"; "err" => %e);
1108+
**cache = LruCache::new(DESCENDANCY_CACHE_SIZE);
1109+
None
1110+
}
1111+
}
1112+
}
1113+
1114+
/// Cache the result of the descendancy check on whether or not the winning block in `key.0`
1115+
/// descends from `key.1`
1116+
fn descendancy_cache_put(
1117+
cache: &mut MutexGuard<'_, LruCache<(SortitionId, BlockHeaderHash), bool>>,
1118+
key: (SortitionId, BlockHeaderHash),
1119+
is_descended: bool,
1120+
) {
1121+
if let Err(e) = cache.insert_clean(key, is_descended) {
1122+
error!("SortitionDB's descendant cache errored. Will continue operation with cleared cache"; "err" => %e);
1123+
**cache = LruCache::new(DESCENDANCY_CACHE_SIZE);
1124+
}
1125+
}
1126+
10941127
/// is the given block a descendant of `potential_ancestor`?
10951128
/// * block_at_burn_height: the burn height of the sortition that chose the stacks block to check
10961129
/// * potential_ancestor: the stacks block hash of the potential ancestor
@@ -1125,39 +1158,36 @@ pub trait SortitionHandle {
11251158
.expect("FATAL: lock poisoned in SortitionDB");
11261159

11271160
while sn.block_height >= earliest_block_height {
1128-
match cache.get(&(sn.sortition_id, potential_ancestor.clone())) {
1129-
Ok(Some(result)) => {
1161+
let cache_check_key = (sn.sortition_id, potential_ancestor.clone());
1162+
match Self::descendancy_cache_get(&mut cache, &cache_check_key) {
1163+
Some(result) => {
11301164
if sn.sortition_id != top_sortition_id {
1131-
if let Err(_) = cache
1132-
.insert_clean((top_sortition_id, potential_ancestor.clone()), result)
1133-
{
1134-
*cache = LruCache::new(2000);
1135-
}
1165+
Self::descendancy_cache_put(
1166+
&mut cache,
1167+
(top_sortition_id, cache_check_key.1),
1168+
result,
1169+
);
11361170
}
11371171
return Ok(result);
11381172
}
11391173
// not cached, don't need to do anything.
1140-
Ok(None) => {}
1141-
// cache is broken, create a new one
1142-
Err(_) => {
1143-
*cache = LruCache::new(2000);
1144-
}
1174+
None => {}
11451175
}
11461176

11471177
if !sn.sortition {
1148-
if let Err(_) =
1149-
cache.insert_clean((top_sortition_id, potential_ancestor.clone()), false)
1150-
{
1151-
*cache = LruCache::new(2000);
1152-
}
1178+
Self::descendancy_cache_put(
1179+
&mut cache,
1180+
(top_sortition_id, cache_check_key.1),
1181+
false,
1182+
);
11531183
return Ok(false);
11541184
}
11551185
if &sn.winning_stacks_block_hash == potential_ancestor {
1156-
if let Err(_) =
1157-
cache.insert_clean((top_sortition_id, potential_ancestor.clone()), true)
1158-
{
1159-
*cache = LruCache::new(2000);
1160-
}
1186+
Self::descendancy_cache_put(
1187+
&mut cache,
1188+
(top_sortition_id, cache_check_key.1),
1189+
true,
1190+
);
11611191
return Ok(true);
11621192
}
11631193

@@ -1193,9 +1223,11 @@ pub trait SortitionHandle {
11931223
}
11941224
}
11951225
}
1196-
if let Err(_) = cache.insert_clean((top_sortition_id, potential_ancestor.clone()), false) {
1197-
*cache = LruCache::new(2000);
1198-
}
1226+
Self::descendancy_cache_put(
1227+
&mut cache,
1228+
(top_sortition_id, potential_ancestor.clone()),
1229+
false,
1230+
);
11991231
return Ok(false);
12001232
}
12011233
}

0 commit comments

Comments
 (0)