[IBD] coins: reduce lookups in dbcache layer propagation #33602

pull l0rinc wants to merge 2 commits into bitcoin:master from l0rinc:l0rinc/BatchWrite-lookup-optimization changing 7 files +27 −34
  1. l0rinc commented at 6:32 pm on October 12, 2025: contributor

    This change is part of [IBD] - Tracking PR for speeding up Initial Block Download

    Summary

    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. On a different path, these caches were recreated needlessly for every block connection.

    Fix for double fetch

    This change uses a single leading try_emplace and branches on the returned inserted flag. In the FRESH && SPENT case (not used in production, 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/bitcoin@723c49b (#32128) and draws simplification ideas bitcoin/bitcoin@ae76ec7 (#30673) and #30326.

    Fix for temporary cache recreation

    Related to parent cache propagation, the second commit makes it possible to avoid destructuring-recreating-destructuring of these short-live parent caches created for each new block. A few temporary CCoinsViewCache’s are destructed right after the Flush(), therefore it is not necessary to call ReallocateCache to recreate them right before they’re killed anyway.

    This change was based on a subset of #28945, the original authors and relevant commenters were added as coauthors to this version.


    Reindex-chainstate indicates ~1% speedup.

     0COMMITS="647cdb4f7e8041affed887e2325ee03a91078bb1 0b0c3293ffd75afb27dadc0b28426b40132a8c6b"; \                       
     1STOP=909090; DBCACHE=4500; \                                                                                                                                                     
     2CC=gcc; CXX=g++; \                                                                      
     3BASE_DIR="/mnt/my_storage"; DATA_DIR="$BASE_DIR/BitcoinData"; LOG_DIR="$BASE_DIR/logs"; \                                                                                        
     4(echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done; echo "") && \
     5hyperfine \                                                                             
     6  --sort command \                                                                      
     7  --runs 2 \                                                                            
     8  --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
     9  --parameter-list COMMIT ${COMMITS// /,} \                                             
    10  --prepare "killall bitcoind 2>/dev/null; rm -f $DATA_DIR/debug.log; git checkout {COMMIT}; git clean -fxd; git reset --hard && \
    11    cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind && \
    12    ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20" \
    13  --cleanup "cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \                                                                                                   
    14  "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0"
    15
    16647cdb4f7e Merge bitcoin/bitcoin#33311: net: Quiet down logging when router doesn't support natpmp/pcp
    170b0c3293ff validation: don't reallocate cache for short-lived CCoinsViewCache                                                                                                    
    18
    19Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 647cdb4f7e8041affed887e2325ee03a91078bb1)
    20  Time (mean ± σ):     16233.508 s ±  9.501 s    [User: 19064.578 s, System: 951.672 s]                                                                                          
    21  Range (min  max):   16226.790 s  16240.226 s    2 runs                                                                                                                       
    22                                                                                        
    23Benchmark 2: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 0b0c3293ffd75afb27dadc0b28426b40132a8c6b)
    24  Time (mean ± σ):     16039.626 s ± 17.284 s    [User: 18870.130 s, System: 950.722 s]
    25  Range (min  max):   16027.405 s  16051.848 s    2 runs
    26  
    27Relative speed comparison
    28        1.01 ±  0.00  COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 647cdb4f7e8041affed887e2325ee03a91078bb1)
    29        1.00          COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=909090 -dbcache=4500 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 0b0c3293ffd75afb27dadc0b28426b40132a8c6b)
    
  2. DrahtBot commented at 6:32 pm on October 12, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33602.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK optout21

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33680 (validation: do not wipe utxo cache for stats/scans/snapshots by l0rinc)
    • #33512 (coins: use number of dirty cache entries in flush warnings/logs by l0rinc)
    • #29700 (kernel, refactor: return error status on all fatal errors by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  3. in src/coins.cpp:252 in 195fc2fe10 outdated
    244@@ -245,12 +245,14 @@ bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &ha
    245     return true;
    246 }
    247 
    248-bool CCoinsViewCache::Flush() {
    249+bool CCoinsViewCache::Flush(bool reallocate_cache) {
    


    optout21 commented at 9:36 am on October 14, 2025:
    How about adding a default value true to the new reallocate_cache parameter, to suggest that that is the more common usage pattern? It also would reduce the diff a bit.

    l0rinc commented at 1:51 pm on October 14, 2025:
    I thought about that, it’s what the original PR did, but we want to see exactly which ones are reallocating and which aren’t - I don’t like implicit behavior, it’s not obvious for this to be true or false by default, both are valid and expected usages so I prefer making it explicit

    optout21 commented at 2:14 pm on October 14, 2025:
    Fair enough. It’s called in more places with ’true’ than with ‘false’, and the original version was corresponding to the ’true’ case, that’s the ’true’ alternative looks more a default. What is important is that comments are added to all places where it is called with ‘false’.

    l0rinc commented at 0:09 am on October 16, 2025:
    Rebased, added explanation to commit message
  4. in src/coins.cpp:188 in b23c6a1fc8 outdated
    181@@ -182,18 +182,16 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
    182 
    183 bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlockIn) {
    184     for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
    185-        // Ignore non-dirty entries (optimization).
    186-        if (!it->second.IsDirty()) {
    187+        if (!it->second.IsDirty()) { // TODO a cursor can only contain dirty entries
    


    optout21 commented at 9:38 am on October 14, 2025:
    This TODO (and the one few lines below) seems to be independent of the change of this commit (it just exposes a pre-existing TODO condition), maybe isolate in a pre commit for clarity.

    l0rinc commented at 1:49 pm on October 14, 2025:
    Yes, it just documents that what we’re modifying here is actually incorrect and needs to be fixed in the future.

    l0rinc commented at 0:09 am on October 16, 2025:
    Added explanation to commit message
  5. optout21 commented at 9:38 am on October 14, 2025: none

    Concept ACK 195fc2fe102197eae27c33b5e3969a6b15d1253a

    Nice optimization

  6. sipa commented at 1:51 pm on October 14, 2025: member
    Why is this Draft?
  7. l0rinc marked this as ready for review on Oct 14, 2025
  8. DrahtBot added the label Needs rebase on Oct 15, 2025
  9. 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 https://github.com/bitcoin/bitcoin/pull/32128/commits/723c49b63bb10da843fbb6efc6928dca415cc47f and draws simplification ideas https://github.com/bitcoin/bitcoin/pull/30673/commits/ae76ec7bcff0a08a61f294882a71e46d177b009f.
    
    Added TODO versions for related pre-existing issues that should be fixed in follow-ups.
    
    Co-authored-by: Martin Ankerl <martin.ankerl@gmail.com>
    Co-authored-by: Andrew Toth <andrewstoth@gmail.com>
    Co-authored-by: optout <13562139+optout21@users.noreply.github.com>
    6657e5127c
  10. validation: don't reallocate cache for short-lived CCoinsViewCache
    A few temporary `CCoinsViewCache`'s are destructed right after the `Flush()`, therefore it is not necessary to call `ReallocateCache` to recreate them right before they're killed anyway.
    
    * `Flush(/*reallocate_cache=*/true)` - retains existing functionality;
    * `Flush(/*reallocate_cache=*/false)` - skips destruction and reallocation of the parent cache since it will soon go out of scope anyway;
    
    For the `reallocate_cache` parameter we want to see exactly which ones will reallocate memory and which won't - since both can be valid usages.
    
    This change was based on a subset of https://github.com/bitcoin/bitcoin/pull/28945.
    
    Co-authored-by: Martin Ankerl <martin.ankerl@gmail.com>
    2d06ed75c5
  11. l0rinc force-pushed on Oct 16, 2025
  12. l0rinc commented at 0:10 am on October 16, 2025: contributor
    Rebased after #32313.
  13. DrahtBot removed the label Needs rebase on Oct 16, 2025

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-10-29 18:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me