fix: speed up GetStateFor (#5100)

## Issue being fixed or feature implemented
should fix #5090 

## What was done?
calculate `nStartHeight` only when it's really needed and using only a
subset of cache that matters for such caclulations

## How Has This Been Tested?
`time dash-cli getblockchaininfo`
before: `real	0m9.211s`
after: `real	0m0.164s`

## Breaking Changes
hopefully none

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have added or updated relevant unit/integration/functional/e2e
tests
- [ ] I have made corresponding changes to the documentation

**For repository code-owners and collaborators only**
- [x] I have assigned this pull request to a milestone

kudos to @nmarley for noticing the issue, @thephez for
testing/confirming/documenting it and to @knst for finding the exact
piece of slow code 👍
This commit is contained in:
UdjinM6 2022-12-13 20:42:52 +03:00 committed by pasta
parent 5f093ea852
commit 33bc6500ab
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984

View File

@ -37,10 +37,33 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
assert(cache.count(pindexPrev));
ThresholdState state = cache[pindexPrev];
auto pindex_search = pindexPrev;
auto state_search = state;
bool do_search{true};
int nStartHeight{std::numeric_limits<int>::max()};
for (const auto& pair : cache) {
if (pair.second == ThresholdState::STARTED && nStartHeight > pair.first->nHeight + 1) {
nStartHeight = pair.first->nHeight + 1;
while (do_search) {
switch (state_search) {
case ThresholdState::DEFINED: {
// not started yet, nothinig to do
do_search = false;
break;
}
case ThresholdState::STARTED: {
nStartHeight = std::min(nStartHeight, pindex_search->nHeight + 1);
// we can walk back here because the only way for STARTED state to exist
// in cache already is to be calculated in previous runs via "walk forward"
// loop below starting from DEFINED state.
pindex_search = pindex_search->GetAncestor(pindex_search->nHeight - nPeriod);
state_search = cache[pindex_search];
break;
}
case ThresholdState::LOCKED_IN:
case ThresholdState::FAILED:
case ThresholdState::ACTIVE: {
// too late, nothing to do
do_search = false;
break;
}
}
}