netsync/manager: prioritize higher height peers for sync peer
This commit modifies the sync peer selection to prefer peers with a higher advertised height than our currently known best height. If no peers are known with a higher height, we will fall back to selecting a random peer with the same best height as our own. The current algorithm currently selects a random peer from the union of these two sets, while this approach will favor trying to make progress. This will likely help in selecting a good peer once already at tip, such as after a restart. Backport of https://github.com/gcash/bchd/pull/96
This commit is contained in:
parent
9bfb2ca034
commit
a9f23321d9
1 changed files with 29 additions and 4 deletions
|
@ -6,6 +6,7 @@ package netsync
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
"container/list"
|
||||||
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
@ -236,7 +237,7 @@ func (sm *SyncManager) startSync() {
|
||||||
}
|
}
|
||||||
|
|
||||||
best := sm.chain.BestSnapshot()
|
best := sm.chain.BestSnapshot()
|
||||||
var bestPeer *peerpkg.Peer
|
var higherPeers, equalPeers []*peerpkg.Peer
|
||||||
for peer, state := range sm.peerStates {
|
for peer, state := range sm.peerStates {
|
||||||
if !state.syncCandidate {
|
if !state.syncCandidate {
|
||||||
continue
|
continue
|
||||||
|
@ -258,9 +259,33 @@ func (sm *SyncManager) startSync() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(davec): Use a better algorithm to choose the best peer.
|
// If the peer is at the same height as us, we'll add it a set
|
||||||
// For now, just pick the first available candidate.
|
// of backup peers in case we do not find one with a higher
|
||||||
bestPeer = peer
|
// height. If we are synced up with all of our peers, all of
|
||||||
|
// them will be in this set.
|
||||||
|
if peer.LastBlock() == best.Height {
|
||||||
|
equalPeers = append(equalPeers, peer)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// This peer has a height greater than our own, we'll consider
|
||||||
|
// it in the set of better peers from which we'll randomly
|
||||||
|
// select.
|
||||||
|
higherPeers = append(higherPeers, peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick randomly from the set of peers greater than our block height,
|
||||||
|
// falling back to a random peer of the same height if none are greater.
|
||||||
|
//
|
||||||
|
// TODO(conner): Use a better algorithm to ranking peers based on
|
||||||
|
// observed metrics and/or sync in parallel.
|
||||||
|
var bestPeer *peerpkg.Peer
|
||||||
|
switch {
|
||||||
|
case len(higherPeers) > 0:
|
||||||
|
bestPeer = higherPeers[rand.Intn(len(higherPeers))]
|
||||||
|
|
||||||
|
case len(equalPeers) > 0:
|
||||||
|
bestPeer = equalPeers[rand.Intn(len(equalPeers))]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start syncing from the best peer if one was selected.
|
// Start syncing from the best peer if one was selected.
|
||||||
|
|
Loading…
Reference in a new issue