Is there an existing issue for this?
- I have searched the existing issues
Current behaviour
Benchcoin has observed an IBD speed regression between commits 9c150222604478431669b66b2caa0d75e8324d4c and 1ea532e590cdc16b86436a2bc4f92d74082307f9: https://bitcoin-dev-tools.github.io/benchcoin/
This includes the following changes:
<details><summary>Details</summary> <p>
src/core/bitcoin on master [$?⇕] via △ v4.1.2 via 🐍 v3.13.13 via ❄️ impure (nix-shell-env)
❯ git range-diff 9c150222604478431669b66b2caa0d75e8324d4c...1ea532e590cdc16b86436a2bc4f92d74082307f9
-: ----------- > 1: fedeff7f201 crypto: disable ASan instrumentation of SSE4 SHA256 for GCC
-: ----------- > 2: 0301c758ea0 wallet migration, fuzz: Migrate hd seed once
-: ----------- > 3: cd912c4e108 wallet: Consolidate generation setup callers into one function
-: ----------- > 4: f713fd1725f refactor: wallet: Don't reuse WALLET_BLANK flag for born-encrypted wallets.
-: ----------- > 5: 80b0c259921 wallet: Load everything into DescSPKM on construction
-: ----------- > 6: 8be5ee554bb test: wallet: Check that loading wallet with both unencrypted and encrypted keys fails.
-: ----------- > 7: 6538f691357 fuzz: Skip adding descriptor to wallet if it cannot be expanded
-: ----------- > 8: aa4f7823aa1 wallet: include keys when constructing DescriptorSPKM during import
-: ----------- > 9: e20aaff70f0 wallet: Construct ExternalSignerSPKM with the new descriptor
-: ----------- > 10: 32946e0291f wallet: Setup new autogenerated descriptors on construction
-: ----------- > 11: 451fdd26a4f test: wallet: Constructing a DSPKM that can't TopUp() throws.
-: ----------- > 12: d5adb9d09b8 doc: fix doxygen links to threads in developer-notes.md
-: ----------- > 13: a815e3e2629 rpc: Correct type for tx_sigops
-: ----------- > 14: 0774eaaf0c2 util: Require integers for SaturatingAdd() and AdditionOverflow()
-: ----------- > 15: a3fe455a953 wallet: refactor to read -walletrbf only once instead of twice
-: ----------- > 16: 813b4a80d7f refactor: introduce SubmitBlock helper
-: ----------- > 17: 5b60f69e40a mining: add submitBlock IPC method to Mining interface
-: ----------- > 18: 3962138cc03 test: add IPC submitBlock functional test
-: ----------- > 19: 0b9e10ad404 guix: Update `python-signapple` and wrap with OpenSSL paths
-: ----------- > 20: d846444d012 guix: Split manifest into build and codesign manifests
-: ----------- > 21: fad4f417d15 test: Use operator<< for time_points instead of manual TickSinceEpoch
-: ----------- > 22: c17cc76a187 test: speed up feature_dbcrash
-: ----------- > 23: a2a2b1745f0 wallet, test: remove -walletrbf startup option from rpc_psbt.py
-: ----------- > 24: 5e833e068d7 wallet, test: -walletrbf startup option from wallet_bumpfee.py
-: ----------- > 25: 0ee94b2fef0 wallet, test: remove -deprecatedrpc=bip125 from wallet_listtransactions.py
-: ----------- > 26: 8cb6e405d88 wallet, test: remove -walletrbf startup option from wallet_listtransactions.py
-: ----------- > 27: 42330922dd8 wallet, test: remove -walletrbf startup option from wallet_backwards_compatibility.py
-: ----------- > 28: fab5733f5d6 doc: Remove good_first_issue.yml
-: ----------- > 29: 4bdd46ace37 ci: switch runners from cirrus to warpbuild
-: ----------- > 30: 58cdb5c2e83 Squashed 'src/leveldb/' changes from ab6c84e6f3..a7f9bdc611
-: ----------- > 31: 4d58c3271c0 build: remove -Wno-conditional-uninitialized from leveldb build
-: ----------- > 32: a9ac680af30 build: remove FALLTHROUGH_INTENDED from leveldb.cmake
-: ----------- > 33: a52ea9bff90 wallet, test: remove -walletrbf startup option from wallet_backwards_compatibility.py
-: ----------- > 34: 3ec550d1688 wallet, test: remove -deprecatedrpc=bip125 from wallet_basic.py
-: ----------- > 35: 307134bd7e2 wallet, test: remove -deprecatedrpc=bip125 from wallet_migration.py
-: ----------- > 36: 2cbbcb5659b wallet, test: remove -deprecatedrpc=bip125 from wallet_send.py
-: ----------- > 37: 7bc39e3d084 wallet, test: add wallet_deprecated_rbf.py for walletrbf deprecated keys & options
-: ----------- > 38: f701cd159af doc: fix typo in release notes of [#34917](/bitcoin-bitcoin/34917/)
-: ----------- > 39: fa51f37f180 doc: Reword the Getting-Started section
-: ----------- > 40: fd44d48b24b wallet: fix ancient wallets migration
-: ----------- > 41: b86c1c443d8 test: add coverage for migrating ancient wallets
</p> </details>
Of these the one which stands out to me is
-: ----------- > 30: 58cdb5c2e83 Squashed 'src/leveldb/' changes from ab6c84e6f3..a7f9bdc611
This change included:
a7f9bdc611 Merge bitcoin-core/leveldb-subtree#52: Revert "Increase maximum read-only mmap()s used from 1000 to 4096 on 64-bit systems"
Benchcoin copies a fixed pruned datadir at height 840,000 and resumes IBD to 900,000. This means the benchmark opens an existing chainstate LevelDB layout created before the LevelDB subtree bump, rather than measuring a database created from scratch by the new LevelDB configuration.
The copied chainstate currently contains 6382 SSTable files:
[root@nixos:/data/pruned-840k]# find chainstate -maxdepth 1 \
\( -name '*.ldb' -o -name '*.sst' \) | wc -l
6382
The LevelDB subtree bump includes a revert of the 64-bit read-only mmap limit from 4096 back to 1000. If the database layout causes many SSTables to be consulted during the resumed sync, the new binary may use the non-mmap random access path for thousands more table files than before. With 6382 SSTable files, the old limit left roughly 4096 files eligible for mmap-backed access and ~2286 beyond the limit, while the new limit leaves only 1000 eligible and ~5382 beyond the limit.
This is only a hypothesis so far; I have not yet confirmed syscall counts, table-cache behavior, or whether the used table set actually crosses the mmap limit.
It also occurs to me that 1a166221cf Merge bitcoin-core/leveldb-subtree#61: Disable seek compaction may interact negatively here by preventing read-triggered compaction from improving an existing layout during the run.
Useful follow-up experiments would be:
- re-run the slow commit with only
kDefaultMmapLimitrestored to 4096; - re-run with seek compaction restored;
- re-run with both restored;
- compare
-debug=leveldb,coindb,benchlogs or syscall profiles for mmap, pread, open/close, table-cache misses, and compaction activity.
I will test the first myself on benchcoin.
If this hypothesis is correct, the regression may affect nodes that upgrade while their chainstate has many SSTables, especially during continued IBD or other read-heavy phases. It may also be worth checking whether long-running tip nodes with large chainstate table counts see a smaller steady-state impact.
Expected behaviour
IBD performance not to degrade
Steps to reproduce
Benchcoin run: https://github.com/bitcoin-dev-tools/benchcoin/actions/runs/26674832655
Relevant log output
No response
How did you obtain Bitcoin Core
Compiled from source
What version of Bitcoin Core are you using?
1ea532e590cdc16b86436a2bc4f92d74082307f9
Operating system and version
Linux nixos 6.6.114
Machine specifications
OS: NixOS 25.05 (Warbler) x86_64 Kernel: Linux 6.6.114 Uptime: 177 days(!), 12 hours, 3 mins Packages: 519 (nix-system) Shell: bash 5.2.37 Terminal: /dev/pts/0 CPU: AMD Ryzen 7 7700 (16) @ 5.39 GHz GPU: AMD Raphael [Integrated] Memory: 2.57 GiB / 62.03 GiB (4%) Swap: Disabled Disk (/): 71.14 GiB / 937.34 GiB (8%) - ext4 Disk (/data): 28.07 GiB / 937.82 GiB (3%) - ext4 Local IP (eno1): 65.21.224.151/26 Locale: en_US.UTF-8