Reduce tx p2p broadcast bandwidth and memory used#9937
Reduce tx p2p broadcast bandwidth and memory used#9937fab-10 merged 43 commits intobesu-eth:mainfrom
Conversation
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> # Conflicts: # CHANGELOG.md # Conflicts: # CHANGELOG.md
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
dd7e7bf to
08ffbb4
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
# Conflicts: # ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetPooledTransactionsFromPeerTask.java
cb5ee00 to
cc230e4
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
cc230e4 to
b9585f7
Compare
…rFetcher` Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
…x requests by size Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
…st-bandwidth # Conflicts: # ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/BufferedGetPooledTransactionsFromPeerFetcher.java # ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/NewPooledTransactionHashesMessageProcessor.java # ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/BufferedGetPooledTransactionsFromPeerFetcherTest.java
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
5753b93 to
34ad1c9
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
34ad1c9 to
d7834fa
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
a903109 to
431a044
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
4eccb7b to
f1159eb
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
There was a problem hiding this comment.
Pull request overview
Reworks transaction broadcast/announcement tracking to reduce redundant P2P traffic and memory usage by centralizing “seen” state and reshaping the sending/fetching flow around per-peer queues and deduplication at ingress.
Changes:
- Replaces per-peer seen sets with a global LRU map keyed by tx hash and per-peer slot-indexed BitSets, plus bounded per-peer send/request queues.
- Refactors senders/processors/fetcher to claim work from
PeerTransactionTracker(single-item claiming, size-bounded batching, and retry behavior aligned to ETH/68). - Updates CLI/config defaults, adds new queue-size option, and refreshes/extends tests for the new APIs.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PeerTransactionTracker.java | Centralizes seen-state & queues; adds connect/disconnect slotting and block-added handling. |
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/BufferedGetPooledTransactionsFromPeerFetcher.java | Fetch loop now pulls announcements from tracker and retries per ETH/68 rules. |
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionsMessageSender.java | Moves to inline filtering + size-limited builder and single-item claiming. |
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/NewPooledTransactionHashesMessageSender.java | Moves to single-item claiming and batch send from tracker-managed queue. |
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/NewPooledTransactionHashesMessageProcessor.java | Delegates dedupe/enqueue to tracker and schedules fetcher task differently. |
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/TransactionsMessage.java | Adds SizeLimitedBuilder and tightens constructor visibility. |
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/RemovalReason.java | Adds stopBroadcasting() to allow immediate queue cleanup on eviction/replacement. |
| app/src/main/java/org/hyperledger/besu/cli/options/TransactionPoolOptions.java | Renames tracked-seen option to global, adds per-peer send-queue cap. |
| ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolConfiguration.java | Adds global tracked-seen limit + per-peer send-queue size defaults. |
| ethereum/eth/build.gradle | Adds commons-collections4 dependency used by new tracker structures. |
| ethereum/eth/src/test/... | Updates and adds tests to match new tracker/sender/fetcher APIs and behaviors. |
.../src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionsMessageSender.java
Show resolved
Hide resolved
.../org/hyperledger/besu/ethereum/eth/transactions/NewPooledTransactionHashesMessageSender.java
Show resolved
Hide resolved
.../org/hyperledger/besu/ethereum/eth/transactions/NewPooledTransactionHashesMessageSender.java
Show resolved
Hide resolved
...eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PeerTransactionTracker.java
Outdated
Show resolved
Hide resolved
...eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PeerTransactionTracker.java
Show resolved
Hide resolved
...g/hyperledger/besu/ethereum/eth/transactions/NewPooledTransactionHashesMessageProcessor.java
Show resolved
Hide resolved
ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/messages/TransactionsMessage.java
Show resolved
Hide resolved
...eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PeerTransactionTracker.java
Show resolved
Hide resolved
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
...th/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionAnnouncement.java
Outdated
Show resolved
Hide resolved
...hyperledger/besu/ethereum/eth/manager/task/BufferedGetPooledTransactionsFromPeerFetcher.java
Show resolved
Hide resolved
...eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PeerTransactionTracker.java
Show resolved
Hide resolved
...eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PeerTransactionTracker.java
Show resolved
Hide resolved
# Conflicts: # CHANGELOG.md
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
app/src/main/java/org/hyperledger/besu/cli/options/TransactionPoolOptions.java
Outdated
Show resolved
Hide resolved
...hyperledger/besu/ethereum/eth/manager/task/BufferedGetPooledTransactionsFromPeerFetcher.java
Outdated
Show resolved
Hide resolved
...hyperledger/besu/ethereum/eth/manager/task/BufferedGetPooledTransactionsFromPeerFetcher.java
Outdated
Show resolved
Hide resolved
...hyperledger/besu/ethereum/eth/manager/task/BufferedGetPooledTransactionsFromPeerFetcher.java
Outdated
Show resolved
Hide resolved
.../src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionsMessageSender.java
Outdated
Show resolved
Hide resolved
# Conflicts: # CHANGELOG.md
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
ahamlat
left a comment
There was a problem hiding this comment.
I see that PeerTransactionTracker.java is becoming a centralized hub, and most of the methods are synchronized (on this). This can have some impact on performance related to the shared lock. After discussing this with @fab-10, and by checking the profiling on lock instances, I'm going to approve for now.
The reason is that I don't see any impact on performance, I don't see more locks than before, and @fab-10 is aware of this strict design. If we observe lock contention under higher peer counts or transaction throughput (e.g., spam events), we should revisit with thread safe data structures and fine grained synchronisation.
The profiling below is during 120 seconds.
|
@macfarla I am merging this one, but if you still have observations, please let me know and I will address them in a follow-up PR |
86c0a75 to
be3a9ab
Compare
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
be3a9ab to
6ebb3ec
Compare
Reduce P2P transaction broadcast bandwidth
Overview
A ground-up rework of transaction broadcast and announcement tracking to significantly reduce both memory usage and redundant P2P traffic.
With default configuration an average of 21% less Java heap memory used, total P2P transaction inbound traffic see at least 80% reduction.
The bandwidth optimization comes from a refactoring of the
PeerTransactionTracker, where all the related queues about tx broadcast are centralized and consolidated, this allowed to specifically reduce duplicate requests the same tx announcement, that were the main reason of the higher bandwidth usage, then there are other smaller improvements, to avoid not useful work, like taking in account confirmed txs and invalid txs dropped from the pool, plus a fine tuning of marking a tx as seen asap.The memory optimization comes without losing any memory, since from collected data the amount of distinct hashes tracked across all peers (with the default configuration of 200_000 max tracked per peer) was always below the 300_000, so in this PR the global hash tracking map, with a max size of 300_000, will behave at least the same in remembering seen transactions.
The core change replaces the previous per-peer
Set<Hash>tracking (one set per peer) with a single globalLRUMap<Hash, PeersSeenState>where eachPeersSeenStateholds two compactBitSets — one for full transactions seen, one for announcements seen — indexed by a per-peer slot number. This eliminates the dominant memory cost: instead ofN_peers × M_hasheshash objects, memory scales withM_hashesonly, with O(1) per-peer membership checks via bit operations.Key changes
PeerTransactionTracker— complete rewriteConcurrentHashMap<EthPeer, Set<Hash>>withLRUMap<Hash, PeersSeenState>, wherePeersSeenStatecontains twoBitSets (transactions / announcements) indexed by peer slotEthPeers.ConnectCallbackto assign stable slot indices to peers on connect, and clears slot bits on disconnect for index reuseBlockAddedObserver: marks confirmed transactions as seen-by-all onHEAD_ADVANCED/CHAIN_REORGevents, suppressing rebroadcast of mined transactionstransactionsToSend) from announcement queues (announcementsToSend), both bounded by the new--Xmax-send-queue-size-per-peeroptionreceivedTransactions/receivedAnnouncementsentry points for deduplication at ingress; newclaimAnnouncementsToRequestFromPeer/consumedAnnouncementsfor the fetcher loopclaimTransactionsToSendToPeer/claimTransactionHashesToSendToPeer(bulk) replaced with single-itemclaimTransactionToSendToPeer/claimAnnouncementToSendToPeerBufferedGetPooledTransactionsFromPeerFetcher— rewritePeerTransactionTrackerinstead of managing its own queueMAX_HASHES) and cumulative byte sizeTransactionsMessageSender/NewPooledTransactionHashesMessageSender— rewriteTransactionsMessage.SizeLimitedBuilder(inline class) replaces the deletedLimitedTransactionsMessagesNewPooledTransactionHashesMessageProcessor/TransactionsMessageProcessorreceivedAnnouncements/receivedTransactionstracker entry points, which return only the fresh subset for further processingETH68-only announcements
TransactionAnnouncementnow always carries type and sizeRemovalReasonstopBroadcasting()method; evicted transactions are removed from all send queues immediately, preventing stale broadcastsCLI / configuration
--Xmax-tracked-seen-txs-per-peerrenamed to--Xmax-tracked-seen-txs(old name kept as deprecated alias) and default raised from 200 000 to 300 000 — the limit is now global, not per-peer--Xmax-send-queue-size-per-peer(default 100 000) caps per-peer send queuesMetrics
p2p_bytes_outbound/p2p_bytes_inboundTesting
PeerTransactionTrackerTest,TransactionsMessageSenderTest,NewPooledTransactionHashesMessageSenderTest,BufferedGetPooledTransactionsFromPeerFetcherTestsubstantially extended and updated to match the new API and registration modelLimitedTransactionsMessagesTestremoved (class deleted);TransactionsMessageTestadded forSizeLimitedBuilderTransactionAnnouncementEncoderDecoderTestadded for the updated announcement encodingFixes
fix #8932
Metrics
P2P Transaction Bandwidth
This graph shows where the main bandwidth reduction occurs, there are less
GetPooledTransactionsrequests, that result in much less incoming traffic from thePooledTransactionsresponse.p2p-a*are the control instances andp2p-b*are the instances running this PRTotal P2P Transaction Inbound traffic see at least 80% reduction

Memory