mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
eth: use hysteresis to stabilize peer selection for transaction broadcast
When maxPeers was just above some perfect square, and a few peers dropped for some reason, we changed the peer selection function. When new peers were acquired, we changed again. This patch stabilizes the selection function under normal operating conditions by adding some hysteresis. Signed-off-by: Csaba Kiraly <csaba.kiraly@gmail.com>
This commit is contained in:
parent
c022c3f8ab
commit
44e3cd5582
1 changed files with 20 additions and 9 deletions
|
|
@ -57,6 +57,9 @@ const (
|
||||||
// All transactions with a higher size will be announced and need to be fetched
|
// All transactions with a higher size will be announced and need to be fetched
|
||||||
// by the peer.
|
// by the peer.
|
||||||
txMaxBroadcastSize = 4096
|
txMaxBroadcastSize = 4096
|
||||||
|
|
||||||
|
// Hysteresis to stabilize the number of direct peers to send transactions to.
|
||||||
|
directPeersHysteresis = 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
var syncChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the sync progress challenge
|
var syncChallengeTimeout = 15 * time.Second // Time allowance for a node to reply to the sync progress challenge
|
||||||
|
|
@ -118,6 +121,7 @@ type handler struct {
|
||||||
txpool txPool
|
txpool txPool
|
||||||
chain *core.BlockChain
|
chain *core.BlockChain
|
||||||
maxPeers int
|
maxPeers int
|
||||||
|
lastDirect int64 // Last number of peers we sent transactions to, used to stabilize the randomness
|
||||||
|
|
||||||
downloader *downloader.Downloader
|
downloader *downloader.Downloader
|
||||||
txFetcher *fetcher.TxFetcher
|
txFetcher *fetcher.TxFetcher
|
||||||
|
|
@ -482,13 +486,20 @@ func (h *handler) BroadcastTransactions(txs types.Transactions) {
|
||||||
annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce
|
annos = make(map[*ethPeer][]common.Hash) // Set peer->hash to announce
|
||||||
)
|
)
|
||||||
// Broadcast transactions to a batch of peers not knowing about it
|
// Broadcast transactions to a batch of peers not knowing about it
|
||||||
sqrtPeers := int64(math.Sqrt(float64(h.peers.len()))) // Approximate number of peers to broadcast to
|
sqrtPeers := math.Sqrt(float64(h.peers.len())) // Approximate number of peers to broadcast to
|
||||||
|
|
||||||
// If maxPeers is just above some perfect square, we need to stabilize
|
// Use some hysteresis to avoid oscillating between two values, stabilising the modulus in the peer selection
|
||||||
// the number to avoid frequent changes when a few peers drop.
|
// If the number of peers is small, use a minimum of 1 peer
|
||||||
maxDirect := int64(math.Sqrt(float64(h.maxPeers)) - 0.5)
|
var directInt int64
|
||||||
direct := big.NewInt(max(min(sqrtPeers, maxDirect), 1))
|
lastDirect := atomic.LoadInt64(&h.lastDirect)
|
||||||
|
if int64(sqrtPeers) >= lastDirect {
|
||||||
|
directInt = max(int64(sqrtPeers), 1)
|
||||||
|
} else {
|
||||||
|
directInt = max(min(int64(sqrtPeers+directPeersHysteresis), lastDirect), 1)
|
||||||
|
}
|
||||||
|
atomic.StoreInt64(&h.lastDirect, directInt)
|
||||||
|
|
||||||
|
direct := big.NewInt(directInt) // Number of peers to send directly to
|
||||||
total := new(big.Int).Exp(direct, big.NewInt(2), nil) // Stabilise total peer count a bit based on sqrt peers
|
total := new(big.Int).Exp(direct, big.NewInt(2), nil) // Stabilise total peer count a bit based on sqrt peers
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue