Perf/ibd speedups#277
Merged
blondfrogs merged 6 commits intomasterfrom Apr 22, 2026
Merged
Conversation
Four unconditional LogPrintf calls were firing on every PON header and every block connect/disconnect during IBD, dominating debug.log volume and measurably slowing sync. Convert them to LogPrint with a category so they only fire under -debug=pon or -debug=fluxnode. - src/pon/pon.cpp: PON difficulty adjustment traces (2x per PON header) - src/fluxnode/fluxnode.cpp: FluxnodeCache::LogDebugData, plus an early-return so the per-block string concatenation over mapStartTxTracker / mapStartTxDOSTracker is skipped when the fluxnode category isn't active.
Fluxd used to allocate 3/4 of -dbcache to the block tree DB whenever -insightexplorer was enabled, which left only ~76 MiB of in-memory UTXO cache at the default -dbcache=450. During IBD this caused frequent full-cache flushes (multi-second stalls every few thousand blocks). Switch to Bitcoin Core's allocation: block tree DB gets 1/8 of the total, capped at 2 MiB without txindex or 1024 MiB with txindex / insightexplorer. Coin DB cache is capped at 8 MiB. The remainder goes to the in-memory UTXO set. At -dbcache=450 with all indexes on, the UTXO cache grows from ~76 MiB to ~386 MiB; at -dbcache=2000 it reaches ~1.7 GiB, which eliminates most flush stalls during IBD.
PR #266 shipped high-bandwidth compact block relay (unsolicited cmpctblock messages to up to three peers). Low-bandwidth mode lets a peer request a compact block on demand via getdata, saving bandwidth for edge peers (light clients, metered connections) that haven't opted into high-bandwidth announcements. Adds MSG_CMPCT_BLOCK as a new inv type, handled by ProcessGetData. When a block is within MAX_CMPCTBLOCK_DEPTH (5 blocks) of the tip, the server responds with a cmpctblock message; older blocks fall back to sending a full block because the requester is unlikely to have the mempool state needed to reconstruct it. Type number 11 is used instead of the BIP 152 canonical value of 4 because type 4 is already allocated to "spork" on the Flux network. IsFluxnodeType() is tightened to an explicit [4, 10] range so the new type isn't misrouted.
CheckForExpiredStartTx and CheckForUndoExpiredStartTx are called on every ConnectBlock/DisconnectBlock. For most of chain history the relevant trackers (mapStartTxTracker, mapStartTxDOSTracker) are empty, so the iterate-and-conditionally-copy loops do no work but still pay for the cs_main-adjacent lock acquisition and the subsequent log lines. Skip the body entirely when there is nothing to do. The emptiness check runs under the lock, so it races correctly with concurrent modifications.
Previously ShrinkDebugFile() only ran at startup and only when -debug was not set (the -shrinkdebugfile default was !fDebug). With debug=1 the log could grow without bound. Changes: - -maxdebugfilesize upper cap is now 10 GiB when -debug is enabled (so a long debug session has room to breathe) and 2 GiB otherwise. The 500 MB default is unchanged. - Default -shrinkdebugfile to true so the cap is enforced even when debug logging is on. - Make ShrinkDebugFile() safe to call at runtime by writing the kept tail to a temp file and atomically renaming; concurrent LogPrintStr writes land on the unlinked inode and fReopenDebugLog is set so the next log write reopens on the new file. - Schedule ShrinkDebugFile() every 5 minutes so a long-running node with heavy debug output doesn't fill the disk between restarts.
Two fixes identified by an audit of fluxd's BIP 152 implementation
against Bitcoin Core:
1. Clean up per-peer compact-block in-flight state on disconnect.
FinalizeNode previously iterated mapPartialBlocks but did nothing
(a TODO comment acknowledged the gap). Peer-keyed cleanup is
actually available via listCompactBlocksInFlight, which stores
{NodeId, block hash} markers. Walk it, drop entries for the
disconnecting peer, and drop the corresponding mapPartialBlocks /
mapPartialBlocksTime entries only when no other peer is still
working on the same block. Prevents a slow memory leak when peers
churn mid-reconstruction.
2. Unify the compact block depth constant as MAX_CMPCTBLOCK_DEPTH,
shared by the cmpctblock reception check and the new low-bandwidth
MSG_CMPCT_BLOCK getdata response. Value is 100, sized to roughly
Bitcoin Core's ~50-minute wall-clock window at fluxd's 30-second
PON block spacing (Bitcoin uses 5 at 10-minute blocks). The prior
reception value of 10 covered only ~5 minutes on PON, which is too
narrow for typical mempool turnover.
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Six focused changes to reduce IBD time and clean up the BIP 152 compact block relay path. Validated against a localhost sync run: full-cache flush stalls eliminated and no behavior regressions observed.
Commits
1. Silence per-block
LogPrintfcalls on sync hot pathFour unconditional
LogPrintfcalls were firing for every PON header and every block connect/disconnect during IBD. Converted toLogPrintwith categories so they only fire under-debug=ponor-debug=fluxnode.src/pon/pon.cpp— PON difficulty/adjustment traces (2× per PON header) →LogPrint("pon", ...)src/fluxnode/fluxnode.cpp—FluxnodeCache::LogDebugDatagets an early-return onLogAcceptCategory("fluxnode")so the per-block string concatenation overmapStartTxTracker/mapStartTxDOSTrackeris skipped when not debugging fluxnodes2. Adopt Bitcoin Core's dbcache split to favor the in-memory UTXO set
Fluxd used to allocate 3/4 of
-dbcacheto the block tree DB whenever-insightexplorerwas enabled, leaving only ~76 MiB for the in-memory UTXO cache at the default-dbcache=450. During IBD this caused frequent full-cache flushes (multi-second stalls every ~4k blocks).Switched to Bitcoin Core's allocation:
Result at
-dbcache=450with all indexes on: UTXO cache grows from ~76 MiB → ~386 MiB. At-dbcache=1000it reaches 867 MiB; at-dbcache=2000it's ~1.7 GiB. Verified zero flush stalls in a 10k-block IBD window vs one 8-second stall every ~4k blocks previously.3. Implement BIP 152 low-bandwidth mode (peer-initiated compact blocks)
#266 shipped high-bandwidth compact block relay (unsolicited
cmpctblockto up to three peers). This adds low-bandwidth mode: lets a peer request a compact block on demand viagetdata, saving bandwidth for edge peers (light clients, metered connections) that haven't opted into high-bandwidth announcements.MSG_CMPCT_BLOCKas a new inv type (value 11, not BIP 152's canonical 4 because type 4 is"spork"on the Flux network)ProcessGetDataresponds toMSG_CMPCT_BLOCKrequests with acmpctblockmessage when the block is within depthIsFluxnodeType()tightened to an explicit[4, 10]range so the new type isn't misroutedOld fluxd peers that don't know type 11 treat it as unknown and silently ignore — no misbehavior, safe to deploy without coordination.
4. Early-return
CheckForExpired/UndoExpiredStartTxwhen tracker is emptyBoth functions are called on every
ConnectBlock/DisconnectBlock. For most of chain history the relevant trackers are empty, so the iterate-and-conditionally-copy loops do no work but still pay for thecs_main-adjacent lock acquisition. The emptiness check runs under the lock so it races correctly with concurrent modifications.5. Cap
debug.logsize and enforce it at runtimePreviously
ShrinkDebugFile()only ran at startup and only when-debugwas not set (-shrinkdebugfiledefault was!fDebug). Withdebug=1the log could grow without bound.-maxdebugfilesizeupper cap is now 10 GiB when-debugis enabled and 2 GiB otherwise. The 500 MB default is unchanged.-shrinkdebugfiledefault flipped totrueso the cap is enforced even when debug logging is on.ShrinkDebugFile()made safe to call at runtime via temp-file + atomic rename +fReopenDebugLog.CScheduler.6. Harden BIP 152 compact block handling
Two fixes identified by an audit against Bitcoin Core's implementation:
a. Clean up per-peer compact-block in-flight state on disconnect.
FinalizeNodepreviously iteratedmapPartialBlocksbut did nothing (a TODO comment acknowledged the gap). Peer-keyed cleanup is actually available vialistCompactBlocksInFlight. Walk it, drop entries for the disconnecting peer, and drop the correspondingmapPartialBlocks/mapPartialBlocksTimeentries only when no other peer is still working on the same block. Prevents a slow memory leak when peers churn mid-reconstruction.b. Unify the compact-block depth constant as
MAX_CMPCTBLOCK_DEPTH, shared by thecmpctblockreception check and the new low-bandwidthMSG_CMPCT_BLOCKgetdata response. Value is 100, sized to roughly Bitcoin Core's ~50-minute wall-clock window at fluxd's 30-second PON block spacing (Bitcoin uses 5 at 10-minute blocks). The prior reception value of 10 covered only ~5 minutes on PON — too narrow for typical mempool turnover.Config / operator impact
-dbcache=450will see their in-memory UTXO cache jump from ~76 MiB → ~386 MiB on restart.Test plan
Related
MSG_CMPCT_BLOCKrequest path when peers advertise LB modepblocktreecompaction (separate change — the block index LevelDB bloats to ~14 GiB without manual compaction during heavy IBD)