Skip to content

Commit b23c6a1

Browse files
l0rincmartinusandrewtoth
committed
coins: reduce lookups in dbcache layer propagation
Previously, when the parent coins cache had no entry and the child did, `BatchWrite` performed a find followed by `try_emplace`, which resulted in multiple `SipHash` computations and bucket traversals on the common insert path. This change uses a single leading `try_emplace` and branches on the returned `inserted` flag. In the `FRESH && SPENT` case (only exercised by tests), we erase the just-inserted placeholder (which is constant time with no rehash anyway). Semantics are unchanged for all valid parent/child state combinations. This change is a minimal version of bitcoin@723c49b and draws simplification ideas bitcoin@ae76ec7. Co-authored-by: Martin Ankerl <[email protected]> Co-authored-by: Andrew Toth <[email protected]>
1 parent 37c21eb commit b23c6a1

File tree

1 file changed

+8
-10
lines changed

1 file changed

+8
-10
lines changed

src/coins.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,18 +182,16 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
182182

183183
bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlockIn) {
184184
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
185-
// Ignore non-dirty entries (optimization).
186-
if (!it->second.IsDirty()) {
185+
if (!it->second.IsDirty()) { // TODO a cursor can only contain dirty entries
187186
continue;
188187
}
189-
CCoinsMap::iterator itUs = cacheCoins.find(it->first);
190-
if (itUs == cacheCoins.end()) {
191-
// The parent cache does not have an entry, while the child cache does.
192-
// We can ignore it if it's both spent and FRESH in the child
193-
if (!(it->second.IsFresh() && it->second.coin.IsSpent())) {
194-
// Create the coin in the parent cache, move the data up
195-
// and mark it as dirty.
196-
itUs = cacheCoins.try_emplace(it->first).first;
188+
auto [itUs, inserted]{cacheCoins.try_emplace(it->first)};
189+
if (inserted) {
190+
if (it->second.IsFresh() && it->second.coin.IsSpent()) {
191+
cacheCoins.erase(itUs); // TODO fresh coins should have been removed at spend
192+
} else {
193+
// The parent cache does not have an entry, while the child cache does.
194+
// Move the data up and mark it as dirty.
197195
CCoinsCacheEntry& entry{itUs->second};
198196
if (cursor.WillErase(*it)) {
199197
// Since this entry will be erased,

0 commit comments

Comments
 (0)