mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
eth: simplify protectedPeers with generic topN helper
Replace peerWithStats wrapper, manual slice copying, and protectTopN closure with a generic topN[T] function that sorts by score and returns top elements. protectedPeers now works directly with []*p2p.Peer slices, building per-category score functions that close over the stats map.
This commit is contained in:
parent
1c518be79f
commit
aa5fa692e2
1 changed files with 33 additions and 29 deletions
|
|
@ -189,6 +189,25 @@ func (cm *dropper) dropRandomPeer() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// topN returns the top n elements from items by score (descending).
|
||||||
|
// Only elements with score > 0 are included. The input slice is not modified.
|
||||||
|
func topN[T any](items []T, n int, score func(T) float64) []T {
|
||||||
|
if n == 0 || len(items) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cp := make([]T, len(items))
|
||||||
|
copy(cp, items)
|
||||||
|
sort.Slice(cp, func(i, j int) bool { return score(cp[i]) > score(cp[j]) })
|
||||||
|
|
||||||
|
var result []T
|
||||||
|
for i := 0; i < n && i < len(cp); i++ {
|
||||||
|
if score(cp[i]) > 0 {
|
||||||
|
result = append(result, cp[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// protectedPeers computes the set of peers that should not be dropped based
|
// protectedPeers computes the set of peers that should not be dropped based
|
||||||
// on inclusion stats. Each protection category independently selects its
|
// on inclusion stats. Each protection category independently selects its
|
||||||
// top-N peers per inbound/dialed pool; the union is returned.
|
// top-N peers per inbound/dialed pool; the union is returned.
|
||||||
|
|
@ -200,42 +219,27 @@ func (cm *dropper) protectedPeers(peers []*p2p.Peer) map[*p2p.Peer]bool {
|
||||||
if len(stats) == 0 {
|
if len(stats) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
type peerWithStats struct {
|
// Split peers by direction.
|
||||||
peer *p2p.Peer
|
var inbound, dialed []*p2p.Peer
|
||||||
s PeerInclusionStats
|
|
||||||
}
|
|
||||||
var inbound, dialed []peerWithStats
|
|
||||||
for _, p := range peers {
|
for _, p := range peers {
|
||||||
entry := peerWithStats{p, stats[p.ID().String()]}
|
|
||||||
if p.Inbound() {
|
if p.Inbound() {
|
||||||
inbound = append(inbound, entry)
|
inbound = append(inbound, p)
|
||||||
} else {
|
} else {
|
||||||
dialed = append(dialed, entry)
|
dialed = append(dialed, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result := make(map[*p2p.Peer]bool)
|
result := make(map[*p2p.Peer]bool)
|
||||||
|
|
||||||
protectTopN := func(entries []peerWithStats, cat protectionCategory) {
|
|
||||||
n := int(float64(len(entries)) * cat.frac)
|
|
||||||
if n == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sort.Slice(entries, func(i, j int) bool {
|
|
||||||
return cat.score(entries[i].s) > cat.score(entries[j].s)
|
|
||||||
})
|
|
||||||
for i := 0; i < n && i < len(entries); i++ {
|
|
||||||
if cat.score(entries[i].s) > 0 {
|
|
||||||
result[entries[i].peer] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, cat := range protectionCategories {
|
for _, cat := range protectionCategories {
|
||||||
inCopy := make([]peerWithStats, len(inbound))
|
// Build a score function that looks up the peer's stats.
|
||||||
copy(inCopy, inbound)
|
score := func(p *p2p.Peer) float64 {
|
||||||
dialCopy := make([]peerWithStats, len(dialed))
|
return cat.score(stats[p.ID().String()])
|
||||||
copy(dialCopy, dialed)
|
}
|
||||||
protectTopN(inCopy, cat)
|
for _, p := range topN(inbound, int(float64(len(inbound))*cat.frac), score) {
|
||||||
protectTopN(dialCopy, cat)
|
result[p] = true
|
||||||
|
}
|
||||||
|
for _, p := range topN(dialed, int(float64(len(dialed))*cat.frac), score) {
|
||||||
|
result[p] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(result) > 0 {
|
if len(result) > 0 {
|
||||||
log.Debug("Protecting high-value peers from drop", "protected", len(result))
|
log.Debug("Protecting high-value peers from drop", "protected", len(result))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue