Optimize rebalanceMesh (#708)

This commit is contained in:
Tanguy 2022-05-25 12:59:33 +02:00 committed by GitHub
parent 60becadcf9
commit 7323ecc9c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 70 additions and 53 deletions

View File

@ -312,22 +312,29 @@ proc rebalanceMesh*(g: GossipSub, topic: string, metrics: ptr MeshMetrics = nil)
var var
prunes, grafts: seq[PubSubPeer] prunes, grafts: seq[PubSubPeer]
npeers = g.mesh.peers(topic) npeers = g.mesh.peers(topic)
defaultMesh: HashSet[PubSubPeer]
backingOff = g.backingOff.getOrDefault(topic)
if npeers < g.parameters.dLow: if npeers < g.parameters.dLow:
trace "replenishing mesh", peers = npeers trace "replenishing mesh", peers = npeers
# replenish the mesh if we're below Dlo # replenish the mesh if we're below Dlo
var candidates = toSeq(
g.gossipsub.getOrDefault(topic, initHashSet[PubSubPeer]()) - var
g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]()) candidates: seq[PubSubPeer]
).filterIt( currentMesh = addr defaultMesh
g.mesh.withValue(topic, v): currentMesh = v
g.gossipSub.withValue(topic, peerList):
for it in peerList[]:
if
it.connected and it.connected and
# avoid negative score peers # avoid negative score peers
it.score >= 0.0 and it.score >= 0.0 and
it notin currentMesh[] and
# don't pick explicit peers # don't pick explicit peers
it.peerId notin g.parameters.directPeers and it.peerId notin g.parameters.directPeers and
# and avoid peers we are backing off # and avoid peers we are backing off
it.peerId notin g.backingOff.getOrDefault(topic) it.peerId notin backingOff:
) candidates.add(it)
# shuffle anyway, score might be not used # shuffle anyway, score might be not used
g.rng.shuffle(candidates) g.rng.shuffle(candidates)
@ -350,20 +357,24 @@ proc rebalanceMesh*(g: GossipSub, topic: string, metrics: ptr MeshMetrics = nil)
else: else:
trace "replenishing mesh outbound quota", peers = g.mesh.peers(topic) trace "replenishing mesh outbound quota", peers = g.mesh.peers(topic)
var candidates = toSeq( var
g.gossipsub.getOrDefault(topic, initHashSet[PubSubPeer]()) - candidates: seq[PubSubPeer]
g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]()) currentMesh = addr defaultMesh
).filterIt( g.mesh.withValue(topic, v): currentMesh = v
g.gossipSub.withValue(topic, peerList):
for it in peerList[]:
if
it.connected and it.connected and
# get only outbound ones # get only outbound ones
it.outbound and it.outbound and
it notin currentMesh[] and
# avoid negative score peers # avoid negative score peers
it.score >= 0.0 and it.score >= 0.0 and
# don't pick explicit peers # don't pick explicit peers
it.peerId notin g.parameters.directPeers and it.peerId notin g.parameters.directPeers and
# and avoid peers we are backing off # and avoid peers we are backing off
it.peerId notin g.backingOff.getOrDefault(topic) it.peerId notin backingOff:
) candidates.add(it)
# shuffle anyway, score might be not used # shuffle anyway, score might be not used
g.rng.shuffle(candidates) g.rng.shuffle(candidates)
@ -439,6 +450,8 @@ proc rebalanceMesh*(g: GossipSub, topic: string, metrics: ptr MeshMetrics = nil)
g.pruned(peer, topic) g.pruned(peer, topic)
g.mesh.removePeer(topic, peer) g.mesh.removePeer(topic, peer)
backingOff = g.backingOff.getOrDefault(topic)
# opportunistic grafting, by spec mesh should not be empty... # opportunistic grafting, by spec mesh should not be empty...
if g.mesh.peers(topic) > 1: if g.mesh.peers(topic) > 1:
var peers = toSeq(try: g.mesh[topic] except KeyError: raiseAssert "have peers") var peers = toSeq(try: g.mesh[topic] except KeyError: raiseAssert "have peers")
@ -448,22 +461,26 @@ proc rebalanceMesh*(g: GossipSub, topic: string, metrics: ptr MeshMetrics = nil)
let median = peers[medianIdx] let median = peers[medianIdx]
if median.score < g.parameters.opportunisticGraftThreshold: if median.score < g.parameters.opportunisticGraftThreshold:
trace "median score below opportunistic threshold", score = median.score trace "median score below opportunistic threshold", score = median.score
var avail = toSeq(
g.gossipsub.getOrDefault(topic, initHashSet[PubSubPeer]()) -
g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]())
)
avail.keepIf do (x: PubSubPeer) -> bool: var
avail: seq[PubSubPeer]
currentMesh = addr defaultMesh
g.mesh.withValue(topic, v): currentMesh = v
g.gossipSub.withValue(topic, peerList):
for it in peerList[]:
if
# avoid negative score peers # avoid negative score peers
x.score >= median.score and it.score >= median.score and
it notin currentMesh[] and
# don't pick explicit peers # don't pick explicit peers
x.peerId notin g.parameters.directPeers and it.peerId notin g.parameters.directPeers and
# and avoid peers we are backing off # and avoid peers we are backing off
x.peerId notin g.backingOff.getOrDefault(topic) it.peerId notin backingOff:
avail.add(it)
# by spec, grab only 2 # by spec, grab only 2
if avail.len > 2: if avail.len > 1:
avail.setLen(2) break
for peer in avail: for peer in avail:
if g.mesh.addPeer(topic, peer): if g.mesh.addPeer(topic, peer):