node: scale default -dbcache with system RAM #34641

pull l0rinc wants to merge 5 commits into bitcoin:master from l0rinc:l0rinc/dynamic-dbcache changing 21 files +228 −90
  1. l0rinc commented at 11:00 pm on February 20, 2026: contributor

    Problem

    -dbcache controls how much RAM Bitcoin Core uses for the in-memory view of the UTXO set, while the authoritative chainstate remains on disk. The default is still the fixed 450 MiB value, chosen almost a decade ago, even though chainstate size and typical hardware profiles have changed significantly since then.

    In practice, a fixed 450 MiB default is often too conservative on modern systems, where larger cache sizes can reduce flush churn and disk roundtrips during validation, especially in IBD. At the same time, memory pressure remains important on smaller systems.

    Historical changes

    Date dbcache change PR
    2016-07-06 100 -> 300 #8273: Bump -dbcache default to 300MiB
    2017-04-05 300 -> 450 #10133: Clean up calculations of pcoinsTip memory usage

    IRC

    The discussion converged on avoiding a single new fixed -dbcache value and moving to RAM-aware defaults instead, balancing performance gains on modern hardware against OOM risk on lower-memory systems.

    Node provider defaults

    • RaspiBlitz sets a higher dbcache during IBD (when no other apps are running), then lowers it afterward.
    • Start9 can set the default dynamically based on total RAM; currently creates a user task to lower dbcache after IBD if it was increased.
    • MyNode automatically adjusts based on system memory (4 GB RAM → 1 GB cache, 8 GB RAM → 2.5 GB cache, 16 GB RAM → 4 GB cache) and also scales max mempool size.
    • Umbrel used to default to 50% RAM during IBD then reduce to 200 MiB post-IBD, but removed that logic because dedicating that much RAM caused issues when users ran other apps; now ships Core defaults.

    Containerization

    Container memory constraints may or may not be reflected by RAM detection. We have considered adding container-detection but decided against it. Startup logs show detected/assumed system memory so users can set -dbcache explicitly when needed.

    Fix

    Measuring -reindex-chainstate on different machines indicates that 450-1024-2048 jumps are all very relevant after which the effects taper off.

    Replace the fixed default with a RAM-aware policy:

    0\text{default\_dbcache}=\mathrm{clamp}\left(100\,\mathrm{MiB},\ 0.25\cdot\left(\text{system RAM}-2\,\mathrm{GiB}\right),\ 2\,\mathrm{GiB}\right)
    

    If system RAM cannot be determined, assume 4 GiB on 64-bit builds and 2 GiB on 32-bit builds. Manual -dbcache values are unchanged and still override the automatic default.

    Warning threshold update

    Oversized -dbcache warnings are kept and aligned with the new policy - warn if:

    • dbcache > default-dbcache when RAM < fallback RAM (4 GiB on 64-bit, 2 GiB on 32-bit)
    • dbcache > 75% of total RAM, otherwise

    Performance measurements

    reindex-chainstate

    Machine 450 MiB 1000 MiB 1536 MiB 2000 MiB 3000 MiB
    M4 Max 16c, 64Gi, SSD 5h 37m 3h 12m 2h 17m 1h 57m
    i7-7700 HDD 8c, 62Gi, HDD 13h 09m 10h 24m 8h 42m 8h 30m
    rpi5-8 4c, 7.7Gi, SSD 52h 06m 36h 24m
    rpi5-16 4c, 15Gi, SSD 13h 35m 12h 10m 10h 54m 10h 45m
    i9-9900K 16c, 62Gi, SSD 6h 07m 5h 28m 5h 05m 4h 57m
    Xeon E5 Win 8c, 31Gi, SSD 10h 28m 9h 30m 8h 36m 8h 24m
    umbrel N150 4c, 15Gi, SSD 9h 20m 8h 19m 7h 52m 7h 45m

     0for DBCACHE in 450 1000 2000 3000; do \
     1  COMMITS="097c18239b58a8ee03794b3ebc6e722a0da30d8d"; \
     2  STOP=936639; CC=gcc; CXX=g++; \
     3  BASE_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) && \
     5  (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | $(lsblk -no ROTA $(df --output=source $BASE_DIR | tail -1) | grep -q 1 && echo HDD || echo SSD)"; echo "") && \
     6  hyperfine \
     7    --sort command \
     8    --runs 1 \
     9    --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
    10    --parameter-list COMMIT ${COMMITS// /,} \
    11    --prepare "killall -9 bitcoind 2>/dev/null; rm -f ./build/bin/bitcoind; git clean -fxd; git reset --hard {COMMIT} && \
    12      cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind -j1 && \
    13      ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log" \
    14    --conclude "killall bitcoind || true; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'Disabling script verification at block [#1](/bitcoin-bitcoin/1/)' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log && grep 'Bitcoin Core version' $DATA_DIR/debug.log | grep -q "$(printf %.12s {COMMIT})"; \
    15                cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \
    16    "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0";
    17done
    

    097c18239b Merge bitcoin/bitcoin#34385: subprocess: Fix -Wunused-private-field when building with clang-cl on Windows

    2026-02-19 | reindex-chainstate | 936639 blocks | dbcache 450 | umbrel | x86_64 | Intel(R) N150 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=450 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        33619.332 s               [User: 61450.140 s, System: 5671.449 s]
    

    2026-02-25 | reindex-chainstate | 936639 blocks | dbcache 1000 | umbrel | x86_64 | Intel(R) N150 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=1000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1
    2  Time (abs ≡):        29948.973 s               [User: 51470.950 s, System: 3405.477 s]
    

    2026-02-25 | reindex-chainstate | 936639 blocks | dbcache 2000 | umbrel | x86_64 | Intel(R) N150 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=2000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        28352.766 s               [User: 46633.422 s, System: 2298.085 s]
    

    2026-02-20 | reindex-chainstate | 936639 blocks | dbcache 3000 | umbrel | x86_64 | Intel(R) N150 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=3000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        27910.440 s               [User: 44917.351 s, System: 2090.958 s]
    
     0for DBCACHE in 450 1000 2000 3000; do \
     1  COMMITS="097c18239b58a8ee03794b3ebc6e722a0da30d8d"; \
     2  STOP=936639; CC=gcc; CXX=g++; \
     3  BASE_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) && \
     5  (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | $(lsblk -no ROTA $(df --output=source $BASE_DIR | tail -1) | grep -q 1 && echo HDD || echo SSD)"; echo "") && \
     6  hyperfine \
     7    --sort command \
     8    --runs 1 \
     9    --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
    10    --parameter-list COMMIT ${COMMITS// /,} \
    11    --prepare "killall -9 bitcoind 2>/dev/null; rm -f ./build/bin/bitcoind; git clean -fxd; git reset --hard {COMMIT} && \
    12      cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind -j1 && \
    13      ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log" \
    14    --conclude "killall bitcoind || true; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'Disabling script verification at block [#1](/bitcoin-bitcoin/1/)' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log && grep 'Bitcoin Core version' $DATA_DIR/debug.log | grep -q "$(printf %.12s {COMMIT})"; \
    15                cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \
    16    "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0";
    17done
    

    097c18239b Merge bitcoin/bitcoin#34385: subprocess: Fix -Wunused-private-field when building with clang-cl on Windows

    2026-02-19 | reindex-chainstate | 936639 blocks | dbcache 450 | rpi5-16-2 | aarch64 | Cortex-A76 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=450 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        48933.904 s               [User: 94560.562 s, System: 7823.574 s]
    

    2026-02-24 | reindex-chainstate | 936639 blocks | dbcache 1000 | rpi5-16-2 | aarch64 | Cortex-A76 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=1000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        43856.539 s               [User: 78451.084 s, System: 5183.434 s]
    

    2026-02-25 | reindex-chainstate | 936639 blocks | dbcache 2000 | rpi5-16-2 | aarch64 | Cortex-A76 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=2000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        39259.025 s               [User: 69044.492 s, System: 3227.006 s]
    

    2026-02-26 | reindex-chainstate | 936639 blocks | dbcache 3000 | rpi5-16-2 | aarch64 | Cortex-A76 | 4 cores | 15Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=3000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        38756.884 s               [User: 65947.478 s, System: 2887.489 s]
    
     0for DBCACHE in 450 1000 1536 2000; do \
     1  COMMITS="097c18239b58a8ee03794b3ebc6e722a0da30d8d"; \
     2  STOP=936639; CC=gcc; CXX=g++; \
     3  BASE_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) && \
     5  (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | $(lsblk -no ROTA $(df --output=source $BASE_DIR | tail -1) | grep -q 1 && echo HDD || echo SSD)"; echo "") && \
     6  hyperfine \
     7    --sort command \
     8    --runs 1 \
     9    --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
    10    --parameter-list COMMIT ${COMMITS// /,} \
    11    --prepare "killall -9 bitcoind 2>/dev/null; rm -f ./build/bin/bitcoind; git clean -fxd; git reset --hard {COMMIT} && \
    12      cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind -j1 && \
    13      ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log" \
    14    --conclude "killall bitcoind || true; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'Disabling script verification at block [#1](/bitcoin-bitcoin/1/)' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log && grep 'Bitcoin Core version' $DATA_DIR/debug.log | grep -q "$(printf %.12s {COMMIT})"; \
    15                cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \
    16    "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0";
    17done
    

    097c18239b Merge bitcoin/bitcoin#34385: subprocess: Fix -Wunused-private-field when building with clang-cl on Windows

    2026-02-19 | reindex-chainstate | 936639 blocks | dbcache 450 | rpi5-8 | aarch64 | Cortex-A76 | 4 cores | 7.7Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=450 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        187564.724 s               [User: 98927.942 s, System: 19100.209 s]
    

    2026-02-25 | reindex-chainstate | 936639 blocks | dbcache 1000 | rpi5-8 | aarch64 | Cortex-A76 | 4 cores | 7.7Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=1000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        132856.721 s               [User: 77471.886 s, System: 13535.639 s]
    

    2026-02-22 | reindex-chainstate | 936639 blocks | dbcache 1536 | rpi5-8 | aarch64 | Cortex-A76 | 4 cores | 7.7Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=1536 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        131061.887 s               [User: 71355.478 s, System: 12038.086 s]
    

    2026-02-27 | reindex-chainstate | 936639 blocks | dbcache 2000 | rpi5-8 | aarch64 | Cortex-A76 | 4 cores | 7.7Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=2000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        125837.682 s               [User: 69422.152 s, System: 11621.279 s]
    
     0for DBCACHE in 450 1000 2000 3000; do \
     1  COMMITS="097c18239b58a8ee03794b3ebc6e722a0da30d8d"; \
     2  STOP=900000; \
     3  DATA_DIR="$HOME/Library/Application Support/Bitcoin"; LOG_DIR="$HOME/bitcoin-reindex-logs"; mkdir -p "$LOG_DIR"; \
     4  COMMA_COMMITS=${COMMITS// /,}; \
     5  (echo ""; for c in $(echo $COMMITS); do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done) && \
     6  (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(sysctl -n machdep.cpu.brand_string) | $(nproc) cores | $(printf '%.1fGiB' "$(( $(sysctl -n hw.memsize)/1024/1024/1024 ))") RAM | SSD | $(sw_vers -productName) $(sw_vers -productVersion) $(sw_vers -buildVersion) | $(xcrun clang --version | head -1)"; echo "") && \
     7  hyperfine \
     8    --sort command \
     9    --runs 1 \
    10    --export-json "$LOG_DIR/rdx-$(echo "$COMMITS" | sed -E 's/([a-f0-9]{8})[a-f0-9]+ ?/\1-/g;s/-$//')-$STOP-$DBCACHE-appleclang.json" \
    11    --parameter-list COMMIT "$COMMA_COMMITS" \
    12    --prepare "killall -9 bitcoind 2>/dev/null || true; rm -f \"$DATA_DIR\"/debug.log; git checkout {COMMIT}; git reset --hard && \
    13      cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release && ninja -C build bitcoind -j2 && \
    14      ./build/bin/bitcoind -datadir=\"$DATA_DIR\" -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20" \
    15    --conclude "killall bitcoind 2>/dev/null || true; sleep 5; grep -q 'height=0' \"$DATA_DIR\"/debug.log && grep -q 'Disabling script verification at block [#1](/bitcoin-bitcoin/1/)' \"$DATA_DIR\"/debug.log && grep -q \"height=$STOP\" \"$DATA_DIR\"/debug.log || { echo 'debug.log assertions failed'; exit 1; }; \
    16                cp \"$DATA_DIR\"/debug.log \"$LOG_DIR\"/debug-{COMMIT}-\$(date +%s).log 2>/dev/null || true" \
    17    "./build/bin/bitcoind -datadir=\"$DATA_DIR\" -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0";
    18done
    

    097c18239b Merge bitcoin/bitcoin#34385: subprocess: Fix -Wunused-private-field when building with clang-cl on Windows

    2026-02-21 | reindex-chainstate | 900000 blocks | dbcache 450 | M4-Max.local | arm64 | Apple M4 Max | 16 cores | 64.0GiB RAM | SSD | macOS 26.2 25C56 | Apple clang version 17.0.0 (clang-1700.6.3.2)

    0Benchmark 1: ./build/bin/bitcoind -datadir="/Users/lorinc/Library/Application Support/Bitcoin" -stopatheight=900000 -dbcache=450 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        20261.315 s               [User: 18768.521 s, System: 4271.673 s]
    

    2026-02-27 | reindex-chainstate | 900000 blocks | dbcache 1000 | M4-Max.local | arm64 | Apple M4 Max | 16 cores | 64.0GiB RAM | SSD | macOS 26.3 25D125 | Apple clang version 17.0.0 (clang-1700.6.3.2)

    0Benchmark 1: ./build/bin/bitcoind -datadir="/Users/lorinc/Library/Application Support/Bitcoin" -stopatheight=900000 -dbcache=1000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        11574.620 s               [User: 12147.446 s, System: 2417.914 s]
    

    2026-02-26 | reindex-chainstate | 900000 blocks | dbcache 2000 | M4-Max.local | arm64 | Apple M4 Max | 16 cores | 64.0GiB RAM | SSD | macOS 26.3 25D125 | Apple clang version 17.0.0 (clang-1700.6.3.2)

    0Benchmark 1: ./build/bin/bitcoind -datadir="/Users/lorinc/Library/Application Support/Bitcoin" -stopatheight=900000 -dbcache=2000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        8226.676 s               [User: 9083.949 s, System: 1179.971 s]
    

    2026-02-21 | reindex-chainstate | 900000 blocks | dbcache 3000 | M4-Max.local | arm64 | Apple M4 Max | 16 cores | 64.0GiB RAM | SSD | macOS 26.2 25C56 | Apple clang version 17.0.0 (clang-1700.6.3.2)

    0Benchmark 1: ./build/bin/bitcoind -datadir="/Users/lorinc/Library/Application Support/Bitcoin" -stopatheight=900000 -dbcache=3000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        7064.184 s               [User: 7701.391 s, System: 668.060 s]
    
     0for DBCACHE in 450 1000 2000 3000; do \
     1  COMMITS="097c18239b58a8ee03794b3ebc6e722a0da30d8d"; \
     2  STOP=936639; CC=gcc; CXX=g++; \
     3  BASE_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) && \
     5  (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | $(lsblk -no ROTA $(df --output=source $BASE_DIR | tail -1) | grep -q 1 && echo HDD || echo SSD)"; echo "") && \
     6  hyperfine \
     7    --sort command \
     8    --runs 1 \
     9    --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
    10    --parameter-list COMMIT ${COMMITS// /,} \
    11    --prepare "killall -9 bitcoind 2>/dev/null; rm -f ./build/bin/bitcoind; git clean -fxd; git reset --hard {COMMIT} && \
    12      cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind -j1 && \
    13      ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log" \
    14    --conclude "killall bitcoind || true; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'Disabling script verification at block [#1](/bitcoin-bitcoin/1/)' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log && grep 'Bitcoin Core version' $DATA_DIR/debug.log | grep -q "$(printf %.12s {COMMIT})"; \
    15                cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \
    16    "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0";
    17done
    

    097c18239b Merge bitcoin/bitcoin#34385: subprocess: Fix -Wunused-private-field when building with clang-cl on Windows

    2026-02-21 | reindex-chainstate | 936639 blocks | dbcache 450 | i7-hdd | x86_64 | Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz | 8 cores | 62Gi RAM | HDD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=450 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        47384.896 s               [User: 54460.024 s, System: 3388.557 s]
    

    2026-02-24 | reindex-chainstate | 936639 blocks | dbcache 1000 | i7-hdd | x86_64 | Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz | 8 cores | 62Gi RAM | HDD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=1000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        37486.190 s               [User: 46563.682 s, System: 2189.609 s]
    

    2026-02-25 | reindex-chainstate | 936639 blocks | dbcache 2000 | i7-hdd | x86_64 | Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz | 8 cores | 62Gi RAM | HDD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=2000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        31379.903 s               [User: 41546.866 s, System: 1383.556 s]
    

    2026-02-21 | reindex-chainstate | 936639 blocks | dbcache 3000 | i7-hdd | x86_64 | Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz | 8 cores | 62Gi RAM | HDD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=3000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        30633.603 s               [User: 39511.869 s, System: 1116.371 s]
    
     0for DBCACHE in 450 1000 2000 3000; do \
     1  COMMITS="5401e673d56198f2c0bad366581e70d5d9cd765c"; \
     2  STOP=933339; \
     3  HOST=x86_64-w64-mingw32; \
     4  XPACK="/home/win/xpack-mingw-w64-gcc-15.2.0-2"; \
     5  BASE_DIR="/mnt/c/my_storage"; DATA_DIR="$BASE_DIR/BitcoinData"; LOG_DIR="$BASE_DIR/logs"; \
     6  WIN_DATA_DIR='C:\\my_storage\\BitcoinData'; \
     7  export PATH="$XPACK/bin:$PATH"; \
     8  mkdir -p "$LOG_DIR"; \
     9  (echo ""; for c in $COMMITS; do git fetch -q origin $c && git log -1 --pretty='%h %s' $c || exit 1; done) && \
    10  (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | win64-gcc15"; echo "") && \
    11  hyperfine \
    12    --sort command \
    13    --runs 1 \
    14    --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-win64.json" \
    15    --parameter-list COMMIT ${COMMITS// /,} \
    16    --prepare "taskkill.exe /IM bitcoind.exe /F 2>/dev/null; rm -f ./build/bin/bitcoind.exe; rm -f $DATA_DIR/debug.log; git clean -fxd -e depends/built -e depends/sources -e depends/$HOST; git reset --hard {COMMIT} && \
    17      make -C depends HOST=$HOST NO_QT=1 NO_ZMQ=1 CC=\"$XPACK/bin/x86_64-w64-mingw32-gcc\" CXX=\"$XPACK/bin/x86_64-w64-mingw32-g++\" -j\$(nproc) && \
    18      cmake -B build -G Ninja --toolchain depends/$HOST/toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_GUI=OFF -DWITH_ZMQ=OFF -DBUILD_TESTS=OFF -DBUILD_BENCH=OFF && \
    19      ninja -C build bitcoind -j\$(nproc) && \
    20      ./build/bin/bitcoind.exe -datadir=\"$WIN_DATA_DIR\" -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log" \
    21    --conclude "taskkill.exe /IM bitcoind.exe /F 2>/dev/null; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log && grep 'Bitcoin Core version' $DATA_DIR/debug.log | grep -q "$(printf %.12s {COMMIT})"; \
    22      cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-\$(date +%s).log" \
    23    "./build/bin/bitcoind.exe -datadir=\"$WIN_DATA_DIR\" -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0"; \
    24done
    

    5401e673d5 Merge bitcoin/bitcoin#33604: p2p: Allow block downloads from peers without snapshot block after assumeutxo validation

    2026-02-10 | reindex-chainstate | 933339 blocks | dbcache 450 | WIN-A2EHOAU4JET | x86_64 | Intel(R) Xeon(R) CPU E5-2637 v2 @ 3.50GHz | 8 cores | 31Gi RAM | win64-gcc15

    0Benchmark 1: ./build/bin/bitcoind.exe -datadir="C:\\my_storage\\BitcoinData" -stopatheight=933339 -dbcache=450 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 5401e673d56198f2c0bad366581e70d5d9cd765c)
    1  Time (abs ≡):        37691.648 s               [User: 0.000 s, System: 0.001 s]
    

    2026-02-24 | reindex-chainstate | 933339 blocks | dbcache 1000 | WIN-A2EHOAU4JET | x86_64 | Intel(R) Xeon(R) CPU E5-2637 v2 @ 3.50GHz | 8 cores | 31Gi RAM | win64-gcc15

    0Benchmark 1: ./build/bin/bitcoind.exe -datadir="C:\\my_storage\\BitcoinData" -stopatheight=933339 -dbcache=1000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 5401e673d56198f2c0bad366581e70d5d9cd765c)
    1  Time (abs ≡):        34250.996 s               [User: 0.002 s, System: 0.000 s]
    

    2026-02-26 | reindex-chainstate | 933339 blocks | dbcache 2000 | WIN-A2EHOAU4JET | x86_64 | Intel(R) Xeon(R) CPU E5-2637 v2 @ 3.50GHz | 8 cores | 31Gi RAM | win64-gcc15

    0Benchmark 1: ./build/bin/bitcoind.exe -datadir="C:\\my_storage\\BitcoinData" -stopatheight=933339 -dbcache=2000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 5401e673d56198f2c0bad366581e70d5d9cd765c)
    1  Time (abs ≡):        31001.091 s               [User: 0.000 s, System: 0.002 s]
    

    2026-02-21 | reindex-chainstate | 933339 blocks | dbcache 3000 | WIN-A2EHOAU4JET | x86_64 | Intel(R) Xeon(R) CPU E5-2637 v2 @ 3.50GHz | 8 cores | 31Gi RAM | win64-gcc15

    0Benchmark 2: ./build/bin/bitcoind.exe -datadir="C:\\my_storage\\BitcoinData" -stopatheight=933339 -dbcache=3000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 5401e673d56198f2c0bad366581e70d5d9cd765c)
    1  Time (abs ≡):        30276.311 s               [User: 0.001 s, System: 0.000 s]
    
     0for DBCACHE in 450 1000 2000 3000; do \                                                                                                                                        
     1  COMMITS="097c18239b58a8ee03794b3ebc6e722a0da30d8d"; \                                                   
     2  STOP=936639; CC=gcc; CXX=g++; \                                                                         
     3  BASE_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) && \
     5  (echo "" && echo "$(date -I) | reindex-chainstate | ${STOP} blocks | dbcache ${DBCACHE} | $(hostname) | $(uname -m) | $(lscpu | grep 'Model name' | head -1 | cut -d: -f2 | xargs) | $(nproc) cores | $(free -h | awk '/^Mem:/{print $2}') RAM | $(lsblk -no ROTA $(df --output=source $BASE_DIR | tail -1) | grep -q 1 && echo HDD || echo SSD)"; echo "") && \
     6  hyperfine \                                                                                             
     7    --sort command \                                                                                      
     8    --runs 1 \                                                                                            
     9    --export-json "$BASE_DIR/rdx-$(sed -E 's/(\w{8})\w+ ?/\1-/g;s/-$//'<<<"$COMMITS")-$STOP-$DBCACHE-$CC.json" \
    10    --parameter-list COMMIT ${COMMITS// /,} \                                                             
    11    --prepare "killall -9 bitcoind 2>/dev/null; rm -f ./build/bin/bitcoind; git clean -fxd; git reset --hard {COMMIT} && \
    12      cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DENABLE_IPC=OFF && ninja -C build bitcoind -j1 && \
    13      ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=1000 -printtoconsole=0; sleep 20; rm -f $DATA_DIR/debug.log" \
    14    --conclude "killall bitcoind || true; sleep 5; grep -q 'height=0' $DATA_DIR/debug.log && grep -q 'Disabling script verification at block [#1](/bitcoin-bitcoin/1/)' $DATA_DIR/debug.log && grep -q 'height=$STOP' $DATA_DIR/debug.log && grep 'Bitcoin Core version' $DATA_DIR/debug.log | grep -q "$(printf %.12s {COMMIT})"; \
    15                cp $DATA_DIR/debug.log $LOG_DIR/debug-{COMMIT}-$(date +%s).log" \
    16    "COMPILER=$CC ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -dbcache=$DBCACHE -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0";
    17done
    

    5401e673d5 Merge bitcoin/bitcoin#33604: p2p: Allow block downloads from peers without snapshot block after assumeutxo validation

    2026-02-26 | reindex-chainstate | 936639 blocks | dbcache 450 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=450 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        22076.658 s               [User: 53940.221 s, System: 3111.267 s]
    

    2026-02-26 | reindex-chainstate | 936639 blocks | dbcache 1000 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=1000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        19724.533 s               [User: 45709.253 s, System: 2066.725 s]
    

    2026-02-26 | reindex-chainstate | 936639 blocks | dbcache 2000 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=2000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        18302.184 s               [User: 40157.899 s, System: 1250.246 s]
    

    2026-02-27 | reindex-chainstate | 936639 blocks | dbcache 3000 | i9-ssd | x86_64 | Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 16 cores | 62Gi RAM | SSD

    0Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=936639 -dbcache=3000 -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 (COMMIT = 097c18239b58a8ee03794b3ebc6e722a0da30d8d)
    1  Time (abs ≡):        17858.670 s               [User: 38277.112 s, System: 1008.751 s]
    

    Quick reference (64 bit)

    System RAM Automatic default Warning fires above
    1 GiB 100 MiB 100 MiB
    2 GiB 100 MiB 100 MiB
    4 GiB 512 MiB 3071 MiB
    8 GiB 1536 MiB 6143 MiB
    16 GiB 2048 MiB 12287 MiB
    32 GiB 2048 MiB 24575 MiB
  2. DrahtBot commented at 11:01 pm on February 20, 2026: contributor

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

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK andrewtoth, willcl-ark, openoms

    If your review is incorrectly listed, please copy-paste <!–meta-tag:bot-skip–> into the comment that the bot should ignore.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #34692 (Bump dbcache to 1 GiB by andrewtoth)
    • #34448 (ci, iwyu: Fix warnings in src/util and treat them as errors by hebasto)
    • #34435 (refactor: use _MiB/_GiB consistently for byte conversions by l0rinc)
    • #34038 (logging: replace -loglevel with -trace, various API improvements by ajtowns)
    • #32427 ((RFC) kernel: Replace leveldb-based BlockTreeDB with flat-file based store by sedited)
    • #29700 (kernel, refactor: return error status on all fatal errors by ryanofsky)
    • #28690 (build: Introduce internal kernel library by sedited)
    • #26022 (Add util::ResultPtr class by ryanofsky)
    • #25665 (refactor: Add util::Result failure types and ability to merge result values 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.

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • MiB (1024) -> MiB (1024^2 bytes) [MiB denotes mebibytes (1024*1024 bytes); “(1024)” is ambiguous/incorrect and should indicate 1024^2 bytes]

    2026-02-27 16:53:05

  3. DrahtBot added the label CI failed on Feb 20, 2026
  4. l0rinc force-pushed on Feb 20, 2026
  5. l0rinc force-pushed on Feb 20, 2026
  6. l0rinc force-pushed on Feb 21, 2026
  7. DrahtBot removed the label CI failed on Feb 21, 2026
  8. l0rinc marked this as ready for review on Feb 21, 2026
  9. l0rinc commented at 1:26 pm on February 21, 2026: contributor

    It took a few rounds to tame (I had a Kernel Panic myself when I saw missing <PLATFORM_ID:Windows>:ws2_32 errors), but it’s ready for review. I will add new measurements to the PR description after I have more instances. If someone could benchmark it on 8 and 4 GB machines, I’d appreciate it. For the record, the bitcoind startup looks like this now:

    02026-02-21T13:24:38Z * Using 2.0 MiB for block index database
    12026-02-21T13:24:38Z * Using 8.0 MiB for chain state database
    22026-02-21T13:24:38Z * Using 2990.0 MiB for in-memory UTXO set (plus up to 286.1 MiB of unused mempool space)
    
  10. in doc/reduce-memory.md:7 in 0f93881cab
    3@@ -4,11 +4,13 @@ There are a few parameters that can be dialed down to reduce the memory usage of
    4 
    5 ## In-memory caches
    6 
    7-The size of some in-memory caches can be reduced. As caches trade off memory usage for performance, reducing these will usually have a negative effect on performance.
    8+The size of some in-memory caches can be reduced. As caches trade off memory for performance, reducing these usually lowers performance.
    


    andrewtoth commented at 10:13 pm on February 21, 2026:
    Not sure we need to update this line? The change doesn’t really add anything.

    l0rinc commented at 11:01 am on February 23, 2026:
    reverted this line
  11. in doc/reduce-memory.md:9 in 0f93881cab
     8+The size of some in-memory caches can be reduced. As caches trade off memory for performance, reducing these usually lowers performance.
     9 
    10-- `-dbcache=<n>` - the UTXO database cache size, this defaults to `450`. The unit is MiB (1024).
    11-  - The minimum value for `-dbcache` is 4.
    12-  - A lower `-dbcache` makes initial sync time much longer. After the initial sync, the effect is less pronounced for most use-cases, unless fast validation of blocks is important, such as for mining.
    13+- `-dbcache=<n>` - UTXO database cache size in MiB (minimum `4`).
    


    andrewtoth commented at 10:16 pm on February 21, 2026:
    Why are we changing this so much? I think we should just remove this defaults to 450`` from this line, and add the below point: - Automatic default scales with system RAM and can be as high as 1000 MiB. Then keep the rest the same.

    l0rinc commented at 11:11 am on February 23, 2026:
    Updated, simplified, thanks.
  12. in doc/release-notes-34641.md:5 in 0f93881cab
    0@@ -0,0 +1,5 @@
    1+Updated `dbcache` default settings
    2+----------------------------------
    3+
    4+- When `-dbcache` is not set explicitly, Bitcoin Core now chooses a RAM-aware default that can be as high as `3000` MiB.
    5+  Explicit `-dbcache` values continue to override the automatic default. (#34641)
    


    andrewtoth commented at 10:17 pm on February 21, 2026:
    I think we should also say something like: “To maintain the same behavior of previous releases, set dbcache to 450.”

    l0rinc commented at 11:11 am on February 23, 2026:
    Done
  13. in src/node/caches.h:23 in 0f93881cab outdated
    20-//! -dbcache default (bytes)
    21-static constexpr size_t DEFAULT_DB_CACHE{DEFAULT_KERNEL_CACHE};
    22+//! Automatic -dbcache floor (bytes)
    23+static constexpr size_t MIN_DEFAULT_DBCACHE{100_MiB};
    24+//! Automatic -dbcache cap (bytes)
    25+static constexpr size_t MAX_DEFAULT_DBCACHE{3000_MiB};
    


    andrewtoth commented at 10:22 pm on February 21, 2026:

    I think we should be more conservative and set this to 1GB as discussed in the IRC meeting. Such a large bump in memory might be unexpected, especially when running bitcoind alongside other applications and not a dedicated node machine.

    0static constexpr size_t MAX_DEFAULT_DBCACHE{1000_MiB};
    

    l0rinc commented at 10:33 pm on February 21, 2026:

    The 1 GB limit was a suggestion for a constant dbcache, which I opposed because it was too high for cheaper nodes (and too low for performant ones). But since we can scale with total memory now, it makes sense to go higher, especially since 3-4 GB already achieves most of the speedup we saw. This way, we have a simple formula instead of custom values for each memory.

    System RAM Automatic default
    1 GiB 100 MiB
    2 GiB 100 MiB
    4 GiB 512 MiB
    8 GiB 1536 MiB
    16 GiB 3000 MiB

    sipa commented at 4:09 pm on February 24, 2026:
    I’m not too worried about this, because I suspect that most low-memory systems have explicit configurations anyway (either because they need it already, or because they’re managed by node-in-a-box / distributions). And we should have loud and clear release notes for this.

    andrewtoth commented at 4:22 pm on February 24, 2026:
    Not really about low memory systems. We don’t clear the cache anymore, so if we sync and then go to steady state the node will use lots of cache for pretty much its lifetime. For instance it finishes IBD at 2GB, it will take maybe a year to fill up to 3GB and finally clear. That’s just being a bad OS citizen using that much memory when we don’t need it.

    sipa commented at 4:31 pm on February 24, 2026:

    Ok that sort of calls for a dbcache value that is different between IBD and later, which I guess makes sense if you’re planning to run other things post-IBD. But on the other hand, a 1 GiB difference seems tiny for sufficiently large systems (which I suspect most non-dedicated setups are).

    Assuming we don’t want to do that in this PR, reducing to 2 GiB or 1 GiB default makes sense perhaps, but that reduces the benefit too.


    andrewtoth commented at 4:34 pm on February 24, 2026:

    What is the difference in benefit? I think more than doubling the default (450->1000) is a pretty big speedup. What’s going from 1->2->3?

    I would think the initial bump would have the lions share of speedup. Could be wrong though.


    sipa commented at 4:39 pm on February 24, 2026:
    You may be right. I haven’t actually used a dbcache setting below 8 GiB or so in years, so :man_shrugging:.

    l0rinc commented at 5:09 pm on February 24, 2026:
    I’m measuring with 1 and 2 cap so that we can compare. Other that that, does the formula make sense?

    andrewtoth commented at 3:59 pm on February 26, 2026:

    There still looks like a substantial benefit to bumping to 1GB.

    Another user posted the same concern as I https://x.com/lukechilds/status/2026875795080359955.

    Perhaps it’s worth doing a conservative bump for now, and work on a separate steady state dbcache value for v32. We could even have a lower general steady state value than 450MB, so running normally uses less RAM. Then we can bump to 3GB or more for IBD in v32.


    l0rinc commented at 10:37 pm on February 26, 2026:

    Yes, now that a few more measurements have come in, it’s clear that the 2 GiB to 3 GiB speedup is negligible. The 1 GiB to 2 GiB is still very much relevant - and affect 16 GiB machines only, 8 GiB machines were already capped at 1536. Changed the upper cap to 2 GiB for now.

    I will push the steady state dbcache change after this change, separately, it makes more sense to restrict that once your parallelization PR lands and we don’t need so much memory anyway.

  14. andrewtoth commented at 10:22 pm on February 21, 2026: contributor
    Concept ACK
  15. l0rinc force-pushed on Feb 23, 2026
  16. in src/node/caches.h:42 in 3e998877db
    39 constexpr bool ShouldWarnOversizedDbCache(size_t dbcache, size_t total_ram) noexcept
    40 {
    41-    const size_t cap{(total_ram < 2048_MiB) ? DEFAULT_DB_CACHE : (total_ram / 100) * 75};
    42-    return dbcache > cap;
    43+    if (total_ram < 2048_MiB) return dbcache > GetDefaultDbCacheBytes();
    44+    else return dbcache > (total_ram / 100) * 75;
    


    sipa commented at 4:12 pm on February 24, 2026:
    Style guide says to always use braces-and-indent when else is present.

    l0rinc commented at 9:59 am on February 25, 2026:
    Thanks, a ternary is even less noisy.
  17. in src/common/system.cpp:114 in 3e998877db outdated
    110@@ -111,22 +111,6 @@ int GetNumCores()
    111     return std::thread::hardware_concurrency();
    112 }
    113 
    114-std::optional<size_t> GetTotalRAM()
    


    sipa commented at 4:13 pm on February 24, 2026:

    In commit “refactor: extract dbcache default helpers”

    Can you split the moveonly aspects and refactorings into separate commits? That would make it more obvious there is no behavior change here.


    l0rinc commented at 9:59 am on February 25, 2026:
    I was hoping someone will suggest that.
  18. in src/init.cpp:506 in 0198116b63
    502@@ -503,7 +503,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
    503     argsman.AddArg("-conf=<file>", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    504     argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
    505     argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", DEFAULT_DB_CACHE_BATCH), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
    506-    argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (minimum %d, default: %d). Make sure you have enough RAM. In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, node::GetDefaultDbCacheBytes() >> 20), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    507+    argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (minimum %s, default: 25%% of (RAM - 2 GiB), clamped between %s and %s; RAM is total system RAM, assumed %s GiB if undetectable). In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, MIN_DEFAULT_DBCACHE >> 20, MAX_DEFAULT_DBCACHE >> 20, FALLBACK_RAM_BYTES >> 30), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    


    sipa commented at 4:17 pm on February 24, 2026:
    Could this report the actual default used?

    l0rinc commented at 9:21 am on February 25, 2026:

    Indeed, added you as coauthor:

    0bin/bitcoind --help | grep -A3 dbcache
    1  -dbcache=<n>
    2       Maximum database cache size <n> MiB (minimum 4, default: 3000 MiB). In
    3       addition, unused memory allocated to the mempool is shared with
    4       this cache (see -maxmempool).
    
  19. l0rinc force-pushed on Feb 25, 2026
  20. l0rinc commented at 10:07 am on February 25, 2026: contributor

    Q: Now that the total memory is needed for more than just the warning, should we mandate that this method works for the whole CI infra (cc: @hebasto), see https://github.com/bitcoin/bitcoin/blob/56791b582958e905e5ba5cbf172a8ea7dad1a8b0/src/test/system_ram_tests.cpp#L18-L21

    I have addresses a few nits, I’m still measuring 1 and 2 GB dbcache values for comparison, added a few ones already to the PR description. The difference between 1 and 3 still seems relevant. I don’t think a 16 GB machine should be surprised by that amount and an 8 GB is already capped at 1536 MB. Let’s see the results and we can decide.

  21. hebasto commented at 10:38 am on February 25, 2026: member

    Q: Now that the total memory is needed for more than just the warning, should we mandate that this method works for the whole CI infra…

    A related discussion happened here: #33435#pullrequestreview-3247240250.

    We could make the test mandatory. If it fails in an unsupported environment, users can still explicitly disable it.

  22. hebasto commented at 10:41 am on February 25, 2026: member
    Could the new source files common/system_ram.cpp and node/dbcache.cpp be added to FILES_WITH_ENFORCED_IWYU?
  23. in src/node/caches.h:35 in 3b2dbda127
    32 
    33 namespace node {
    34+//! Compute the automatic -dbcache size from total RAM, reserving memory for non-dbcache usage.
    35+constexpr size_t GetDefaultCache(size_t total_ram) noexcept
    36+{
    37+    const int64_t raw_default_dbcache{(int64_t(total_ram) - RESERVED_RAM) / 4}; // 25% of remaining memory
    


    willcl-ark commented at 11:45 am on February 25, 2026:

    Seems annoying to have this as int64_t when everything else is size_t

    How about if we used here:

    0      const size_t usable = total_ram > RESERVED_RAM ? total_ram - RESERVED_RAM : 0;
    1      return std::clamp(usable / 4, MIN_DEFAULT_DBCACHE, MAX_DEFAULT_DBCACHE);
    

    then we could have RESERVED_RAM as sizet like the rest of the constants?


    l0rinc commented at 12:03 pm on February 25, 2026:
    I avoided std::clamp since it’s undefined when min > max, but I don’t think that’s relevant here since they’re constants. Thanks, added you as coauthor.
  24. willcl-ark commented at 11:50 am on February 25, 2026: member

    Concept ACK

    Seems like a reasonable first step towards something more like #8437, which I’ve wanted to see for a long time… In the case that never happens, this seems perfectly worthwhile on it’s own, too.

    Just one comment so far, re. handling the implementation-defined truncation, but mostly LGTM.

  25. l0rinc force-pushed on Feb 25, 2026
  26. l0rinc commented at 12:06 pm on February 25, 2026: contributor
    Thanks @hebasto & @willcl-ark, addressed your concerns, added both as coauthor.
  27. hebasto commented at 12:19 pm on February 25, 2026: member

    Could the new source files common/system_ram.cpp and node/dbcache.cpp be added to FILES_WITH_ENFORCED_IWYU?

    The IWYU warnings in the CI seem to be legit.

  28. l0rinc force-pushed on Feb 25, 2026
  29. DrahtBot added the label CI failed on Feb 25, 2026
  30. in src/node/caches.h:21 in 7385c5bd62 outdated
    18 //! min. -dbcache (bytes)
    19 static constexpr size_t MIN_DB_CACHE{4_MiB};
    20-//! -dbcache default (bytes)
    21-static constexpr size_t DEFAULT_DB_CACHE{DEFAULT_KERNEL_CACHE};
    22+//! Automatic -dbcache floor (bytes)
    23+static constexpr size_t MIN_DEFAULT_DBCACHE{100_MiB};
    


    sedited commented at 12:23 pm on February 25, 2026:
    I’m still not sure about reducing the default dbcache. The project has defaulted to 450 for nearly a decade. Looking through the issue tracker, I have not found too many users complaining about bitcoind oom-ing on low-RAM devices. Even the most popular raspberry pi installation guide bumps cache to 2GB: https://raspibolt.org/guide/bitcoin/bitcoin-client.html#configuration (I realize though that they are targeting devices with 4+GB of RAM). Do we really need to change this on the minimum side?

    l0rinc commented at 1:00 pm on February 25, 2026:

    I have not found too many users complaining about bitcoind oom-ing on low-RAM devices

    I have tried it and we can’t do it with 2 GB total memory currently with default dbcache. The memory usage grows with threads, with mempool, with sigcache, connection count, memory buffers, etc. With 4 GB ram we’re already increasing the dbcache in this PR, so reduction only happens for extremely constrained machines. A 2 GB machine can barely finish an IBD and only if we explicitly reduce the dbcache to 100 (and even this OOM-ed on some flushes). That’s what we’re doing here automatically now. A 2 GB machine can’t even compile the source code without explicit swapping, so it makes sense to make these more realistic.


    sedited commented at 1:19 pm on February 25, 2026:
    How does the same reasoning apply to virtualizations where e.g. 2GB are allocated to running bitcoind in a jail? Reading through some of the issues in the tracker that seems a likely deployment.

    andrewtoth commented at 1:32 pm on February 25, 2026:
    I am running nodes in 2GB AWS EC2 instances just fine. Although mempool is fairly empty. I don’t think IBD in such an instance is feasible though, with or without dbcache. Reducing this for steady state seems fine. I doubt users will notice. Not sure why anyone would want to build on such an instance either.
  31. l0rinc force-pushed on Feb 25, 2026
  32. in src/common/system_ram.cpp:25 in c4077b3da7
    20+{
    21+    [[maybe_unused]] auto clamp{[](uint64_t v) { return size_t(std::min(v, uint64_t{std::numeric_limits<size_t>::max()})); }};
    22+#ifdef WIN32
    23+    if (MEMORYSTATUSEX m{}; (m.dwLength = sizeof(m), GlobalMemoryStatusEx(&m))) return clamp(m.ullTotalPhys);
    24+#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__illumos__) || defined(__linux__)
    25+    if (long p{sysconf(_SC_PHYS_PAGES)}, s{sysconf(_SC_PAGESIZE)}; p > 0 && s > 0) return clamp(1ULL * p * s);
    


    sedited commented at 12:51 pm on February 25, 2026:
    I’m not sure if this will work correctly in a containerized environment. E.g. what happens if you create a docker container with bounded memory? From what I am gathering it will attempt to measure the hosts memory, not whatever the system administrator allocated for the container. I’m not sure if we can account for all these scenarios, meaning this change is likely to break a few deployments. A log message on init indicating what was measured and how much db cache allocation was scaled up would already go a ways to at least make this a bit more transparent.

    l0rinc commented at 6:21 pm on February 25, 2026:

    Thanks, this was exactly what I was working on after talking to @openoms.

    We could extend the total memory calculator to take cgroups and BSD jails into consideration, but for now (to avoid bikeshedding here), I only added a warning if /sys/fs/cgroup exists. That extra warning also made me realize that we are not displaying the cache sizes in a uniform way, and there is no point in pretending we care about decimals for MiB, but we do for GiB. Since GiB is now the expected unit for -dbcache, I unified the display of the cache units.

    Total RAM is also cached now so that we can call it multiple times, and it was renamed to TryGetTotalRam to differentiate it from the alternative that falls back to the default value.

    Also made GetDefaultCache more testable by reverting to system ran if the optional parameter is not provided.

    And lastly I regrouped the tests (data separated from logic) to simplify the RAM-aware commit diff.


    l0rinc commented at 10:33 pm on February 26, 2026:
    Reverted many of these based on followup reviews
  33. DrahtBot removed the label CI failed on Feb 25, 2026
  34. openoms commented at 3:20 pm on February 25, 2026: none

    Concept ACK

    For context, I am a maintainer of the RaspiBlitz project and regularly coach users on running nodes. My own setups range from Raspberry Pi 5 with 8 GiB to 64 GiB PCs, and I also run bitcoind within Kubernetes clusters.

    The RAM-aware default is a worthwhile change on all fronts:

    • Low-RAM machines (1-2 GiB): Reducing the default below 450 MiB is welcome. These systems need every bit of headroom for other services — a typical node box runs bitcoind alongside LND/CLN, Electrs, and various middleware. Having bitcoind be as lightweight as possible on constrained hardware matters.

    • Normal machines (4-32 GiB): The 0.25 * (RAM - 2 GiB) formula with a 3 GiB cap makes sense. The benchmarks show clear gains, and the scaling is proportional.

    • High-RAM machines (32+ GiB): Capping at 3 GiB is the right call. These machines aren’t typically dedicated to bitcoind alone, and the benchmarks show diminishing returns beyond that point — no reason to claim more memory than the performance gain justifies.

    On the container question raised by @sedited — this is relevant for Kubernetes deployments where cgroups limit memory. A log line showing the detected RAM and resulting dbcache default would help operators verify the right thing is happening.

  35. l0rinc force-pushed on Feb 25, 2026
  36. l0rinc force-pushed on Feb 25, 2026
  37. DrahtBot added the label CI failed on Feb 25, 2026
  38. DrahtBot commented at 6:58 pm on February 25, 2026: contributor

    🚧 At least one of the CI tasks failed. Task 32 bit ARM: https://github.com/bitcoin/bitcoin/actions/runs/22410084554/job/64880875328 LLM reason (✨ experimental): Compilation failed due to -Werror errors in tests (caches_tests.cpp) during build.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  39. l0rinc force-pushed on Feb 25, 2026
  40. l0rinc force-pushed on Feb 25, 2026
  41. l0rinc force-pushed on Feb 25, 2026
  42. DrahtBot removed the label CI failed on Feb 25, 2026
  43. in src/node/caches.cpp:35 in 5127078e47
    27@@ -27,6 +28,15 @@ static constexpr size_t MAX_FILTER_INDEX_CACHE{1024_MiB};
    28 //! Max memory allocated to tx spenderindex DB specific cache in bytes.
    29 static constexpr size_t MAX_TXOSPENDER_INDEX_CACHE{1024_MiB};
    30 
    31+namespace {
    32+bool CGroupFilesystemPresent() noexcept
    33+{
    34+    // If present, the process may run under external memory limits (e.g. containers).
    35+    static const bool cgroup_present{fs::exists("/sys/fs/cgroup")};
    


    willcl-ark commented at 10:35 am on February 26, 2026:

    I think this file exists on ~ all bare-metal linux machines though.

    0core/worktrees/pr-34641 on  pr-34641 [$] via △ v4.1.2 via 🐍 v3.13.11 via ❄️  impure (nix-shell-env)
    1❯ eza /sys/fs/cgroup
    2cgroup.controllers      cgroup.threads         dev-hugepages.mount  io.pressure       memory.stat                    sys-kernel-config.mount
    3cgroup.max.depth        cpu.pressure           dev-mqueue.mount     io.prio.class     memory.zswap.writeback         sys-kernel-debug.mount
    4cgroup.max.descendants  cpu.stat               dmem.capacity        io.stat           misc.capacity                  sys-kernel-tracing.mount
    5cgroup.pressure         cpu.stat.local         dmem.current         irq.pressure      misc.current                   system.slice
    6cgroup.procs            cpuset.cpus.effective  init.scope           memory.numa_stat  misc.peak                      user.slice
    7cgroup.stat             cpuset.cpus.isolated   io.cost.model        memory.pressure   proc-sys-fs-binfmt_misc.mount
    8cgroup.subtree_control  cpuset.mems.effective  io.cost.qos          memory.reclaim    sys-fs-fuse-connections.mount
    

    So I think the LogWarning will fire on every linux node, which is not optimal.

    0LogWarning("Automatic -dbcache sizing may not reflect external memory limits. Set -dbcache explicitly if needed.");
    

    Not sure what to suggest though, sorry. I did read how systemd approaches this, which could be inspiring? https://github.com/systemd/systemd/blob/8a2b2828ccca56523b32a58ce5a5687044a2898f/src/basic/virt.c#L632


    l0rinc commented at 11:50 am on February 26, 2026:

    Thanks for checking, I can reproduce it:

    cmake -B build -DBUILD_GUI=OFF -DENABLE_IPC=OFF >/dev/null 2>&1 && cmake –build build –target bitcoind -j >/dev/null 2>&1 && timeout 30 ./build/bin/bitcoind -regtest -printtoconsole=1 | grep ‘warning’

    2026-02-26T11:21:23Z [warning] Automatic -dbcache sizing may not reflect external memory limits. Set -dbcache explicitly if needed


    I need to find a better way to detect containerization - as you said, it won’t be perfect, but we can make it better later if the warnings appear for unexpected cases (or vice-versa). Or maybe you’re right that since we’re showing the detected max memory and since we’re already warning in the release notes, we can add containerization detection/handling independently. I’ll push this for now, let’s see what other reviewers think!


    sedited commented at 1:01 pm on February 26, 2026:
    I don’t think detecting is worthwhile, there are probably too many cases to take care of here. Besides, this log line can also just be logged unconditionally (maybe with a slightly changed wording).

    sipa commented at 1:06 pm on February 26, 2026:
    One case that it won’t detect is inside a real VM (qemu, kvm, …) where the guest has its own kernel. However, memory detection may still be unreliable in that case, though perhaps not to the same extent as containers. You may have multiple guests on the same hosts, with memory allocations to them that exceed the host’s available memory, using memory ballooning to let them share it.

    fanquake commented at 1:16 pm on February 26, 2026:

    I don’t think detecting is worthwhile, there are probably too many cases to take care of here.

    I agree. I don’t think we need to try and detect containerisation.


    sipa commented at 3:43 pm on February 26, 2026:
    Yeah let’s drop this commit.

    l0rinc commented at 10:32 pm on February 26, 2026:
    Dropped container detection
  44. in src/common/system.h:38 in 11c1b13e54
    34@@ -35,6 +35,6 @@ int GetNumCores();
    35 /**
    36  * Return the total RAM available on the current system, if detectable.
    37  */
    38-std::optional<size_t> GetTotalRAM();
    39+std::optional<size_t> TryGetTotalRam();
    


    sipa commented at 3:35 pm on February 26, 2026:

    In commit “system: move TryGetTotalRam() to common/system_ram.cpp

    If the implementation moves to common/system_ram.cpp, then the declaration should move to common/system_ram.h.


    l0rinc commented at 10:32 pm on February 26, 2026:
    Indeed, done
  45. in src/node/dbcache.cpp:10 in 3bafb8c9ca
     5+#include <node/caches.h>
     6+#include <algorithm>
     7+#include <cstddef>
     8+
     9+namespace node {
    10+size_t GetDefaultCache() noexcept
    


    sipa commented at 3:42 pm on February 26, 2026:

    In commit “refactor: extract dbcache default helpers”

    I’d expect the definition for this in node/dbcache.h, or the implementation in node/caches.cpp.


    l0rinc commented at 10:32 pm on February 26, 2026:
    Done, thanks
  46. in src/node/caches.cpp:86 in 0c60d6e606
    82@@ -77,8 +83,8 @@ void LogOversizedDbCache(const ArgsManager& args) noexcept
    83     if (const auto total_ram{TryGetTotalRam()}) {
    84         const size_t db_cache{CalculateDbCacheBytes(args)};
    85         if (ShouldWarnOversizedDbCache(db_cache, *total_ram)) {
    86-            InitWarning(bilingual_str{tfm::format(_("A %zu MiB dbcache may be too large for a system memory of only %zu MiB."),
    87-                        db_cache >> 20, *total_ram >> 20)});
    88+            InitWarning(bilingual_str{tfm::format(_("A %s dbcache may be too large for a system memory of only %s."),
    


    sipa commented at 3:51 pm on February 26, 2026:

    In commit “node: unify human-readable dbcache size logs”

    I don’t think we need this commit right now?


    l0rinc commented at 10:32 pm on February 26, 2026:
    Reverted
  47. sipa commented at 4:25 pm on February 26, 2026: member

    From today’s meeting:

    011:06:18 < andrewtoth_> Not sure if l0rinc is here, but he opened [#34641](/bitcoin-bitcoin/34641/) after last week's meeting. Would be nice to get that in for v31
    111:06:21 < corebot> [#34641](/bitcoin-bitcoin/34641/) | node: scale `-dbcache` default from total system RAM by l0rinc · Pull Request [#34641](/bitcoin-bitcoin/34641/) · bitcoin/bitcoin · GitHub
    2...
    311:06:42 < fanquake> I think if we want to get that in for 31, we want to try and stem the scope creep there
    411:06:56 < sipa> fanquake: i just left some comments to that effect
    511:07:00 < fanquake> Trying to do stuff like detecting containerisation, is too much, for what could be a one-liner change plus release notes
    611:07:18 < andrewtoth_> fair feedback
    7...
    811:08:19 < sipa> but i think it's worthwhile, absent 31132, it's a very simple and probably very practically beneficial improvement for many users
    911:08:45 < andrewtoth_> sipa: indeed
    
  48. darosior commented at 6:00 pm on February 26, 2026: member

    My recollection from last week’s meeting was that we’d simply do a more moderate default bump than was initially proposed. All the detection this PR is trying to do might make sense for a later effort (though i’m not convinced yet), but this seems way too much post feature-freeze for 31.

    Can we just trim this down to simply the default bump for 31? (Could also be done in a separate PR.)

  49. andrewtoth commented at 6:13 pm on February 26, 2026: contributor

    Last week I believe we had consensus to detect RAM and if <2GB = 100MB 2-4GB = 400MB >4GB = 1000MB

    If unsure about RAM, I say fallback to current default.

  50. l0rinc commented at 10:19 pm on February 26, 2026: contributor

    Appreciate all the feedback, pushed a new version.

    • TryGetTotalRam() was moved to a dedicated common/system_ram.h and includes were updated accordingly.
    • Moved dbcache-related constants and helper logic to dedicated node/dbcache.h and node/dbcache.cpp.
    • Dropped scope-creep parts: cache-size formatter (FormatDbCacheSize), container detection warning (LogCGroupMemoryLimitWarning), and the local post-IBD lower-dbcache experiment.
    • Based on review feedback and 450/1000/2000/3000 measurements, the first three steps show the major gains, while improvements beyond 2 GiB are marginal. The automatic upper cap is now 2 GiB (docs/release notes updated to 100 MiB..2 GiB).
    • This cap change affects 16 GiB systems and above; 8 GiB still defaults to 1536 MiB.
    • Kept explicit wording that the selected value applies to both IBD and steady-state.
  51. l0rinc force-pushed on Feb 26, 2026
  52. l0rinc force-pushed on Feb 26, 2026
  53. DrahtBot added the label CI failed on Feb 26, 2026
  54. DrahtBot removed the label CI failed on Feb 26, 2026
  55. in src/node/caches.cpp:29 in fbbc6162c7 outdated
    28@@ -25,19 +29,16 @@ static constexpr size_t MAX_TX_INDEX_CACHE{1024_MiB};
    29 static constexpr size_t MAX_FILTER_INDEX_CACHE{1024_MiB};
    30 //! Max memory allocated to tx spenderindex DB specific cache in bytes.
    31 static constexpr size_t MAX_TXOSPENDER_INDEX_CACHE{1024_MiB};
    32-//! Maximum dbcache size on 32-bit systems.
    33-static constexpr size_t MAX_32BIT_DBCACHE{1024_MiB};
    


    sedited commented at 6:18 am on February 27, 2026:
    Shouldn’t we still have a special case for this?

    l0rinc commented at 8:11 am on February 27, 2026:
  56. l0rinc renamed this:
    node: scale `-dbcache` default from total system RAM
    node: scale default `-dbcache` with system RAM
    on Feb 27, 2026
  57. in ci/test/03_test_script.sh:183 in 797d2600eb outdated
    182@@ -183,7 +183,7 @@ fi
    183 
    


    ismaelsadeeq commented at 1:22 pm on February 27, 2026:

    In “system: move TryGetTotalRam() to common/system_ram.cpp797d2600eb9ae395d6e6e889fa10425a5c667896

    This does more than just a move, perhaps do a move, only commit that can be reviewed with --color-moved=zebra

    And a subsequent commit that does the changes, renames, and using static variable?


    l0rinc commented at 3:26 pm on February 27, 2026:
    It’s difficult to a cleaner move, I tried to keep it minimal, explained in the commit message why - do you have a concrete suggestion?

    ismaelsadeeq commented at 3:41 pm on February 27, 2026:

    do you have a concrete suggestion?

    If it’s not a clean move, when retouching, the commit title should be refactor not move something like “refactor: split TryGetTotalRam() from common/system.cpp”


    l0rinc commented at 3:52 pm on February 27, 2026:
    Reworder to say migrate
  58. in src/node/dbcache.h:20 in 847ef0a9f9 outdated
    15+static constexpr size_t MIN_DB_CACHE{4_MiB};
    16+//! -dbcache default (bytes)
    17+static constexpr size_t DEFAULT_DB_CACHE{450_MiB};
    18+//! Maximum dbcache size on current architecture.
    19+static constexpr size_t MAX_DBCACHE_BYTES{SIZE_MAX == UINT64_MAX ? std::numeric_limits<size_t>::max() : 1024_MiB};
    20+
    


    ismaelsadeeq commented at 1:40 pm on February 27, 2026:

    In “refactor: extract dbcache default helpers” 847ef0a9f9aefe712d80d5c750e65e1cc7e726a8 While we are here, we should define and reuse a variable instead of constant

    0static constexpr int MiB_SHIFT = 20; // 2^20 = 1 MiB
    

    l0rinc commented at 3:28 pm on February 27, 2026:
    We’re using these shifts all over the code - but it does improve a bit after #34435 where we’re simply dividing by e.g. 1_MiB or 1_GiB instead of shifting. To minimize diffs I kept the current style for now.
  59. in src/node/caches.h:28 in 847ef0a9f9
    23@@ -28,10 +24,11 @@ struct CacheSizes {
    24     kernel::CacheSizes kernel;
    25 };
    26 CacheSizes CalculateCacheSizes(const ArgsManager& args, size_t n_indexes = 0);
    27+
    28 constexpr bool ShouldWarnOversizedDbCache(size_t dbcache, size_t total_ram) noexcept
    


    ismaelsadeeq commented at 1:48 pm on February 27, 2026:

    In “refactor: extract dbcache default helpers” 847ef0a9f9aefe712d80d5c750e65e1cc7e726a8

    This should also move to dbcache.{h/cpp}?


    l0rinc commented at 3:52 pm on February 27, 2026:
    Good point, moved in refactor: extract dbcache default helpers, thanks, added you as coauthor.
  60. in src/test/caches_tests.cpp:16 in e642139bf2
    11+#include <limits>
    12+
    13 using namespace node;
    14 
    15+namespace {
    16+void CheckWarnThreshold(size_t threshold, size_t total_ram)
    


    ismaelsadeeq commented at 2:14 pm on February 27, 2026:

    In “test: tighten current dbcache warning tests” e642139bf2857b8536a072226537b4b0ce05b14e

    nit:

    0void CheckWarnBbCacheThreshold(size_t db_cache_threshold, size_t total_ram)
    

    l0rinc commented at 3:52 pm on February 27, 2026:
    Done something similar
  61. andrewtoth commented at 2:26 pm on February 27, 2026: contributor

    I pushed #34692 as an alternative to this for v31.

    I think this is on the right track, but is too complex to get enough review to get into the next release.

    To do this properly, we should separate IBD and steady state dbcache. I think we can do this for v32. Simply bumping to 1GB when we can will still be a big benefit to most users.

  62. in src/init.cpp:506 in d1d104c4fa outdated
    502@@ -503,7 +503,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
    503     argsman.AddArg("-conf=<file>", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    504     argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
    505     argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", DEFAULT_DB_CACHE_BATCH), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
    506-    argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (minimum %d, default: %d). Make sure you have enough RAM. In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, node::GetDefaultCache() >> 20), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    507+    argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (minimum %s, default: %s MiB). In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, node::GetDefaultCache() >> 20), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
    


    ismaelsadeeq commented at 2:59 pm on February 27, 2026:

    In “node: make default dbcache RAM-aware” d1d104c4fa7c1f46091ff3124be716841a401030

    Why was the warning removed? -dbcache still overrides the default, so users passing oversized values should still be warned.


    The help string should mention the minimum value and note that values below it will be clamped, so users aren’t surprised when their input is silently adjusted.


    l0rinc commented at 3:38 pm on February 27, 2026:
    We can’t add all the info here, I wanted to make sure this is high level without a lot of details. As described in the commit message, now that we have a dedicated warning we don’t have to explain in static code, we will guide the user explicitly.
  63. ismaelsadeeq commented at 3:16 pm on February 27, 2026: member

    Reviewed to e642139bf2857b8536a072226537b4b0ce05b14e and did a light code review of d1d104c4fa7c1f46091ff3124be716841a401030

    Tested on two environments:

    Apple M2 Pro — macOS Tahoe 26.1 (25B78), 16 GB RAM

    02026-02-27T14:59:24Z Automatically selected -dbcache=2048 MiB based on detected system memory of 16384 MiB.
    

    Ryzen 7700 — NixOS, 64 GB RAM

    02026-02-27T15:05:24Z Automatically selected -dbcache=2048 MiB based on detected system memory of 63406 MiB.
    
  64. l0rinc force-pushed on Feb 27, 2026
  65. l0rinc force-pushed on Feb 27, 2026
  66. DrahtBot added the label CI failed on Feb 27, 2026
  67. DrahtBot commented at 4:02 pm on February 27, 2026: contributor

    🚧 At least one of the CI tasks failed. Task 32 bit ARM: https://github.com/bitcoin/bitcoin/actions/runs/22493280473/job/65160976971 LLM reason (✨ experimental): Compiler error: MIN_DB_CACHE is not declared in optionsdialog.cpp, causing the build to fail.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  68. system: migrate `TryGetTotalRam()` to `common/system_ram.cpp`
    Move the OS-dependent total RAM query from `common/system.cpp` into a dedicated `common/system_ram.cpp` translation unit and declare it in `common/system_ram.h`.
    
    Update call sites to include `common/system_ram.h` and rename `GetTotalRAM()` to `TryGetTotalRam()`.
    Add `common/system_ram` to `FILES_WITH_ENFORCED_IWYU` so this new source is checked at error level.
    Since we use it for more than just warnings now, make `system_ram_tests` require RAM detection instead of skipping when unavailable.
    
    Co-authored-by: sipa <sipa@bitcoincore.org>
    Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
    e5d09eaa4b
  69. l0rinc force-pushed on Feb 27, 2026
  70. refactor: extract `dbcache` default helpers
    Move the fixed `-dbcache` default (450 MiB) out of `kernel` and into `node`.
    This makes it reusable without a kernel-only constant.
    Wire `node/dbcache.cpp` into `bitcoin_node` and `bitcoinkernel`, and add `common/system_ram.cpp` to `bitcoinkernel` build inputs.
    
    Introduce `node::GetDefaultCache()` and `MAX_DBCACHE_BYTES`.
    
    The helper still returns the fixed default in this commit.
    Later commits make it RAM-aware.
    
    Co-authored-by: ismaelsadeeq <abubakarsadiqismail@proton.me>
    d6ceeac0e6
  71. test: tighten current `dbcache` warning tests
    Exercise the current `dbcache` default and oversized warning policy.
    The default remains fixed at `DEFAULT_DB_CACHE` (450 MiB).
    
    Below 2 GiB total RAM, the warning cap is `DEFAULT_DB_CACHE`.
    At and above 2 GiB, the cap is 75% of total RAM.
    
    Also assert the default `dbcache` never triggers the oversized warning.
    
    Co-authored-by: ismaelsadeeq <abubakarsadiqismail@proton.me>
    92e8beece0
  72. node: make default `dbcache` RAM-aware
    The fixed `-dbcache` default of 450 MiB is too high for small systems and too conservative for larger ones.
    Compute the automatic default as `std::clamp((max(total_ram - 2 GiB, 0) / 4), 100 MiB, 2 GiB)`.
    The 2 GB upper limit was chosen because it's still a lot faster than 1 GiB, but barely faster than 3 GiB.
    
    When RAM detection is unavailable, fall back to 4 GiB on 64-bit and 2 GiB on 32-bit.
    Use that fallback for default calculation and logging.
    
    Align oversized `-dbcache` warnings with this policy on low-memory systems.
    For total RAM below `FALLBACK_RAM_BYTES`, warn when the configured value exceeds the automatic default.
    Keep the 75% of total RAM warning cap for larger systems.
    
    Log the automatically selected default when `-dbcache` is not explicitly set.
    
    And now that we have warnings for excessive dbcache in the logs, we can remove the warning from `-dbcache` arg doc.
    
    Co-authored-by: Pieter Wuille <pieter@wuille.net>
    Co-authored-by: willcl-ark <will8clark@gmail.com>
    8bffaf7239
  73. doc: add release notes for updated `dbcache` defaults
    Also update related docs.
    
    Co-authored-by: Andrew Toth <andrewstoth@gmail.com>
    a6ec8c960b
  74. l0rinc force-pushed on Feb 27, 2026
  75. DrahtBot removed the label CI failed on Feb 27, 2026
  76. rustaceanrob commented at 10:42 am on February 28, 2026: contributor

    Reindex chainstate benchmark:

     0#!/usr/bin/env bash
     1set -euo pipefail
     2
     3SRC_DIR="${SRC_DIR:-$HOME/bitcoin-core/review}"
     4COMMIT_A="${COMMIT_A:-701b8d714861874449c3360f31bdb01512f10644}"
     5COMMIT_B="${COMMIT_B:-fbbc6162c7e9ad4c13c99442849fc279b98803d3}"
     6STOP="${STOP:-930000}"
     7# DBCACHE="${DBCACHE:-450}"
     8DATA_DIR="${DATA_DIR:-/data1}"
     9JOBS="${JOBS:-$(nproc)}"
    10
    11git reset --hard $COMMIT_A
    12cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_GUI=OFF -DWITH_ZMQ=OFF -DBUILD_TESTS=OFF -DBUILD_BENCH=OFF --log-level=ERROR
    13ninja -C build bitcoind -j $JOBS
    14time ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 -daemon=0
    15
    16git reset --hard $COMMIT_B
    17cmake -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_GUI=OFF -DWITH_ZMQ=OFF -DBUILD_TESTS=OFF -DBUILD_BENCH=OFF --log-level=ERROR
    18ninja -C build bitcoind -j $JOBS
    19time ./build/bin/bitcoind -datadir=$DATA_DIR -stopatheight=$STOP -reindex-chainstate -blocksonly -connect=0 -printtoconsole=0 -daemon=0
    
    0$ lscpu
    1Architecture:             x86_64
    2  CPU op-mode(s):         32-bit, 64-bit
    3  ...
    4CPU(s):                   16
    5  ...
    6  Model name:             AMD Ryzen 7 7700 8-Core Processor
    
    0$ free -h
    1               total        used        free      shared  buff/cache   available
    2Mem:            62Gi       5.3Gi       1.4Gi        16Mi        56Gi        56Gi
    

    Before

    0HEAD is now at 701b8d7148 Merge bitcoin/bitcoin#34609: test: remove appveyor reference in comment
    1...
    2real	217m15.813s
    3user	425m36.988s
    4sys	52m50.304s
    

    After

    0HEAD is now at fbbc6162c7 doc: add release notes for updated `dbcache` defaults
    1...
    2real	176m13.200s
    3user	325m36.977s
    4sys	23m54.572s
    

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: 2026-03-04 03:13 UTC

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