Skip to content

Commit 8fc24bd

Browse files
Merge dashpay#6734: perf: temporary cache for consequent calls of CDeterministicMNList for historical blocks
366cd2b refactor: clarify logic and add a named constant MINI_SNAPSHOT_INTERVAL (Konstantin Akimov) bfca726 perf: do not create mini-snapshots during re-index (Konstantin Akimov) 38513b6 perf: temporary cache for consequent calls of CDeterministicMNList for historical blocks (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Each call of `CDeterministicMNManager::GetListForBlock` for historical block can require up to 575 diff applying from snapshot. Consequent calls for close blocks repeat this calculation twice. ## What was done? This PR abuses `mnListsCache` by adding mini-snapshot each 32 blocks between snapshots in database (each 576 blocks). Downside of this solution: extra RAM usage. Though, this cache is cleaned every 10 seconds by `CDeterministicMNManager::DoMaintenance`, so, the RAM usage is temporary. ## How Has This Been Tested? It speeds up RPC `protx diff` up to 8x. `develop`: ``` $ time ( for j in $(seq 500) ; do src/dash-cli protx diff $((2121000+$j)) $((2121000+$j+1)) ; done ) > /dev/null real 0m47,743s user 0m0,472s sys 0m1,467s ``` PR: ``` $ time ( for j in $(seq 500) ; do src/dash-cli protx diff $((2121000+$j)) $((2121000+$j+1)) ; done ) > /dev/null real 0m6,032s user 0m0,423s sys 0m1,300s ``` It speeds ups blocks's Undo up to 10x; measured by calling `invalidateblock blockhash` where blockhash is distant block, far from the tip (500+). ## Breaking Changes N/A ## Checklist: - [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 - [x] I have assigned this pull request to a milestone ACKs for top commit: UdjinM6: LGTM, utACK 366cd2b Tree-SHA512: 1880783916394b6f45a0e71dc59c454766bff498df62cc4642dfa4e8a53736de2ac7c180397584572b4c21a651f65b26cb832c7e4cf2d4b9599556f58bda621e
2 parents c2335e9 + 366cd2b commit 8fc24bd

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

src/evo/deterministicmns.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <consensus/validation.h>
1717
#include <deploymentstatus.h>
1818
#include <messagesigner.h>
19+
#include <node/blockstorage.h>
1920
#include <script/standard.h>
2021
#include <stats/client.h>
2122
#include <uint256.h>
@@ -779,6 +780,23 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlockInternal(gsl::not_n
779780
for (const auto& diffIndex : listDiffIndexes) {
780781
const auto& diff = mnListDiffsCache.at(diffIndex->GetBlockHash());
781782
snapshot.ApplyDiff(diffIndex, diff);
783+
784+
static constexpr int MINI_SNAPSHOT_INTERVAL = 32;
785+
if (!node::fReindex && snapshot.GetHeight() % MINI_SNAPSHOT_INTERVAL == 0) {
786+
// Add this temporary mini-snapshot to the cache.
787+
// Persistent masternode list snapshots are stored in evo-db every 576 blocks.
788+
// To answer GetListForBlock() between these snapshots, the node must rebuild
789+
// state by applying up to 575 diffs from the nearest persistent snapshot.
790+
// If GetListForBlock() is called repeatedly in that range, the work multiplies
791+
// (up to 575 diffs * number of calls).
792+
// Mini-snapshots reduce this overhead by caching intermediate states
793+
// every MINI_SNAPSHOT_INTERVAL blocks. Unlike persistent snapshots, these live
794+
// only in memory and are cleaned up after a short time by the scheduled cleanup().
795+
// There is also separate in-memory caching for the current tip and active quorums,
796+
// but this mini-snapshot cache specifically speeds up repeated requests
797+
// for nearby historical blocks.
798+
mnListsCache.emplace(snapshot.GetBlockHash(), snapshot);
799+
}
782800
}
783801

784802
if (tipIndex) {

0 commit comments

Comments
 (0)