Unverified Commit 260be2a2 authored by Aarsh Shah's avatar Aarsh Shah Committed by GitHub

Reduce allocs in AddPeer (#81)

* reduce allocs while adding peer
parent eb2adab8
......@@ -43,7 +43,7 @@ func newBucket() *bucket {
// returns all peers in the bucket
// it is safe for the caller to modify the returned objects as it is a defensive copy
func (b *bucket) peers() []PeerInfo {
var ps []PeerInfo
ps := make([]PeerInfo, 0, b.len())
for e := b.list.Front(); e != nil; e = e.Next() {
p := e.Value.(*PeerInfo)
ps = append(ps, *p)
......@@ -51,6 +51,28 @@ func (b *bucket) peers() []PeerInfo {
return ps
}
// returns the "minimum" peer in the bucket based on the `lessThan` comparator passed to it.
// It is NOT safe for the comparator to mutate the given `PeerInfo`
// as we pass in a pointer to it.
// It is NOT safe to modify the returned value.
func (b *bucket) min(lessThan func(p1 *PeerInfo, p2 *PeerInfo) bool) *PeerInfo {
if b.list.Len() == 0 {
return nil
}
minVal := b.list.Front().Value.(*PeerInfo)
for e := b.list.Front().Next(); e != nil; e = e.Next() {
val := e.Value.(*PeerInfo)
if lessThan(val, minVal) {
minVal = val
}
}
return minVal
}
// return the Ids of all the peers in the bucket.
func (b *bucket) peerIds() []peer.ID {
ps := make([]peer.ID, 0, b.list.Len())
......
package kbucket
import (
"testing"
"time"
"github.com/libp2p/go-libp2p-core/test"
"github.com/stretchr/testify/require"
)
func TestBucketMinimum(t *testing.T) {
t.Parallel()
b := newBucket()
require.Nil(t, b.min(func(p1 *PeerInfo, p2 *PeerInfo) bool { return true }))
pid1 := test.RandPeerIDFatal(t)
pid2 := test.RandPeerIDFatal(t)
pid3 := test.RandPeerIDFatal(t)
// first is min
b.pushFront(&PeerInfo{Id: pid1, LastUsefulAt: time.Now()})
require.Equal(t, pid1, b.min(func(first *PeerInfo, second *PeerInfo) bool {
return first.LastUsefulAt.Before(second.LastUsefulAt)
}).Id)
// first is till min
b.pushFront(&PeerInfo{Id: pid2, LastUsefulAt: time.Now().AddDate(1, 0, 0)})
require.Equal(t, pid1, b.min(func(first *PeerInfo, second *PeerInfo) bool {
return first.LastUsefulAt.Before(second.LastUsefulAt)
}).Id)
// second is the min
b.pushFront(&PeerInfo{Id: pid3, LastUsefulAt: time.Now().AddDate(-1, 0, 0)})
require.Equal(t, pid3, b.min(func(first *PeerInfo, second *PeerInfo) bool {
return first.LastUsefulAt.Before(second.LastUsefulAt)
}).Id)
}
......@@ -183,18 +183,19 @@ func (rt *RoutingTable) addPeer(p peer.ID, queryPeer bool) (bool, error) {
// the bucket to which the peer belongs is full. Let's try to find a peer
// in that bucket with a LastSuccessfulOutboundQuery value above the maximum threshold and replace it.
allPeers := bucket.peers()
for _, pc := range allPeers {
if time.Since(pc.LastUsefulAt) > rt.usefulnessGracePeriod {
minLast := bucket.min(func(first *PeerInfo, second *PeerInfo) bool {
return first.LastUsefulAt.Before(second.LastUsefulAt)
})
if time.Since(minLast.LastUsefulAt) > rt.usefulnessGracePeriod {
// let's evict it and add the new peer
if bucket.remove(pc.Id) {
if bucket.remove(minLast.Id) {
bucket.pushFront(&PeerInfo{Id: p, LastUsefulAt: lastUsefulAt, LastSuccessfulOutboundQueryAt: time.Now(),
dhtId: ConvertPeerID(p)})
rt.PeerAdded(p)
return true, nil
}
}
}
return false, ErrPeerRejectedNoCapacity
}
......
......@@ -78,6 +78,7 @@ func TestBucket(t *testing.T) {
t.Fatalf("split failed. found id with cpl == 0 in non 0 bucket")
}
}
}
func TestNPeersForCpl(t *testing.T) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment