Some gossip fixes (#467)

* fix some missing rpc in rebalanceMesh

* clarify some variable names and lifetime

* further improvements
This commit is contained in:
Giovanni Petrantoni 2020-12-01 19:44:09 +09:00 committed by GitHub
parent 94e672ead0
commit b4738d723c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 45 additions and 49 deletions

View File

@ -411,40 +411,40 @@ proc rebalanceMesh(g: GossipSub, topic: string) {.async.} =
# create a mesh topic that we're subscribing to # create a mesh topic that we're subscribing to
var var
grafts, prunes, grafting: seq[PubSubPeer] prunes, grafts: seq[PubSubPeer]
let npeers = g.mesh.peers(topic) let npeers = g.mesh.peers(topic)
if npeers < g.parameters.dLow: if npeers < g.parameters.dLow:
trace "replenishing mesh", peers = g.mesh.peers(topic) trace "replenishing mesh", peers = npeers
# replenish the mesh if we're below Dlo # replenish the mesh if we're below Dlo
grafts = toSeq( var candidates = toSeq(
g.gossipsub.getOrDefault(topic, initHashSet[PubSubPeer]()) - g.gossipsub.getOrDefault(topic, initHashSet[PubSubPeer]()) -
g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]()) g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]())
).filterIt(it.connected) ).filterIt(
it.connected and
grafts.keepIf do (x: PubSubPeer) -> bool:
# avoid negative score peers # avoid negative score peers
x.score >= 0.0 and it.score >= 0.0 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 it.peerId notin g.backingOff
)
# shuffle anyway, score might be not used # shuffle anyway, score might be not used
shuffle(grafts) shuffle(candidates)
# sort peers by score, high score first since we graft # sort peers by score, high score first since we graft
grafts.sort(byScore, SortOrder.Descending) candidates.sort(byScore, SortOrder.Descending)
# Graft peers so we reach a count of D # Graft peers so we reach a count of D
grafts.setLen(min(grafts.len, g.parameters.d - g.mesh.peers(topic))) candidates.setLen(min(candidates.len, g.parameters.d - npeers))
trace "grafting", grafts = grafts.len trace "grafting", grafting = candidates.len
for peer in grafts: for peer in candidates:
if g.mesh.addPeer(topic, peer): if g.mesh.addPeer(topic, peer):
g.grafted(peer, topic) g.grafted(peer, topic)
g.fanout.removePeer(topic, peer) g.fanout.removePeer(topic, peer)
grafting &= peer grafts &= peer
else: else:
var meshPeers = toSeq(g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]())) var meshPeers = toSeq(g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]()))
@ -452,45 +452,44 @@ proc rebalanceMesh(g: GossipSub, topic: string) {.async.} =
if meshPeers.len < g.parameters.dOut: if meshPeers.len < g.parameters.dOut:
trace "replenishing mesh outbound quota", peers = g.mesh.peers(topic) trace "replenishing mesh outbound quota", peers = g.mesh.peers(topic)
grafts = toSeq( var candidates = toSeq(
g.gossipsub.getOrDefault(topic, initHashSet[PubSubPeer]()) - g.gossipsub.getOrDefault(topic, initHashSet[PubSubPeer]()) -
g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]()) g.mesh.getOrDefault(topic, initHashSet[PubSubPeer]())
).filterIt(
it.connected and
# get only outbound ones
it.outbound and
# avoid negative score peers
it.score >= 0.0 and
# don't pick explicit peers
it.peerId notin g.parameters.directPeers and
# and avoid peers we are backing off
it.peerId notin g.backingOff
) )
grafts.keepIf do (x: PubSubPeer) -> bool:
# get only outbound ones
x.outbound and
# avoid negative score peers
x.score >= 0.0 and
# don't pick explicit peers
x.peerId notin g.parameters.directPeers and
# and avoid peers we are backing off
x.peerId notin g.backingOff
# shuffle anyway, score might be not used # shuffle anyway, score might be not used
shuffle(grafts) shuffle(candidates)
# sort peers by score, high score first, we are grafting # sort peers by score, high score first, we are grafting
grafts.sort(byScore, SortOrder.Descending) candidates.sort(byScore, SortOrder.Descending)
# Graft peers so we reach a count of D # Graft peers so we reach a count of D
grafts.setLen(min(grafts.len, g.parameters.dOut)) candidates.setLen(min(candidates.len, g.parameters.dOut))
trace "grafting outbound peers", topic, peers = grafts.len trace "grafting outbound peers", topic, peers = candidates.len
for peer in grafts: for peer in candidates:
if g.mesh.addPeer(topic, peer): if g.mesh.addPeer(topic, peer):
g.grafted(peer, topic) g.grafted(peer, topic)
g.fanout.removePeer(topic, peer) g.fanout.removePeer(topic, peer)
grafting &= peer grafts &= peer
if g.mesh.peers(topic) > g.parameters.dHigh: if g.mesh.peers(topic) > g.parameters.dHigh:
# prune peers if we've gone over Dhi # prune peers if we've gone over Dhi
prunes = toSeq(g.mesh[topic]) prunes = toSeq(g.mesh[topic])
# avoid pruning peers we are currently grafting in this heartbeat # avoid pruning peers we are currently grafting in this heartbeat
prunes.keepIf do (x: PubSubPeer) -> bool: x notin grafting prunes.keepIf do (x: PubSubPeer) -> bool: x notin grafts
let mesh = prunes
# shuffle anyway, score might be not used # shuffle anyway, score might be not used
shuffle(prunes) shuffle(prunes)
@ -511,28 +510,25 @@ proc rebalanceMesh(g: GossipSub, topic: string) {.async.} =
else: else:
inbound &= peer inbound &= peer
let
meshOutbound = prunes.countIt(it.outbound)
maxOutboundPrunes = meshOutbound - g.parameters.dOut
# ensure that there are at least D_out peers first and rebalance to g.d after that # ensure that there are at least D_out peers first and rebalance to g.d after that
let maxOutboundPrunes =
block:
var count = 0
for peer in mesh:
if peer.outbound:
inc count
count - g.parameters.dOut
outbound.setLen(min(outbound.len, max(0, maxOutboundPrunes))) outbound.setLen(min(outbound.len, max(0, maxOutboundPrunes)))
# concat remaining outbound peers # concat remaining outbound peers
inbound &= outbound prunes = inbound & outbound
let pruneLen = inbound.len - g.parameters.d let pruneLen = prunes.len - g.parameters.d
if pruneLen > 0: if pruneLen > 0:
# Ok we got some peers to prune, # Ok we got some peers to prune,
# for this heartbeat let's prune those # for this heartbeat let's prune those
shuffle(inbound) shuffle(prunes)
inbound.setLen(pruneLen) prunes.setLen(pruneLen)
trace "pruning", prunes = inbound.len trace "pruning", prunes = prunes.len
for peer in inbound: for peer in prunes:
g.pruned(peer, topic) g.pruned(peer, topic)
g.mesh.removePeer(topic, peer) g.mesh.removePeer(topic, peer)
@ -565,7 +561,7 @@ proc rebalanceMesh(g: GossipSub, topic: string) {.async.} =
for peer in avail: for peer in avail:
if g.mesh.addPeer(topic, peer): if g.mesh.addPeer(topic, peer):
g.grafted(peer, topic) g.grafted(peer, topic)
grafting &= peer grafts &= peer
trace "opportunistic grafting", peer trace "opportunistic grafting", peer
when defined(libp2p_expensive_metrics): when defined(libp2p_expensive_metrics):