Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove a lot of allocations, and fix some ambiguous naming #30

Merged
merged 2 commits into from
Apr 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 33 additions & 32 deletions sorting.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,49 @@ type peerDistance struct {
distance ID
}

// peerSorterArr implements sort.Interface to sort peers by xor distance
type peerSorterArr []*peerDistance
// peerDistanceSorter implements sort.Interface to sort peers by xor distance
type peerDistanceSorter struct {
peers []peerDistance
target ID
}

func (p peerSorterArr) Len() int { return len(p) }
func (p peerSorterArr) Swap(a, b int) { p[a], p[b] = p[b], p[a] }
func (p peerSorterArr) Less(a, b int) bool {
return p[a].distance.less(p[b].distance)
func (pds *peerDistanceSorter) Len() int { return len(pds.peers) }
func (pds *peerDistanceSorter) Swap(a, b int) { pds.peers[a], pds.peers[b] = pds.peers[b], pds.peers[a] }
func (pds *peerDistanceSorter) Less(a, b int) bool {
return pds.peers[a].distance.less(pds.peers[b].distance)
}

//
// Append the peer.ID to the sorter's slice. It may no longer be sorted.
func (pds *peerDistanceSorter) appendPeer(p peer.ID) {
pds.peers = append(pds.peers, peerDistance{
p: p,
distance: xor(pds.target, ConvertPeerID(p)),
})
}

func copyPeersFromList(target ID, peerArr peerSorterArr, peerList *list.List) peerSorterArr {
if cap(peerArr) < len(peerArr)+peerList.Len() {
newArr := make(peerSorterArr, len(peerArr), len(peerArr)+peerList.Len())
copy(newArr, peerArr)
peerArr = newArr
}
for e := peerList.Front(); e != nil; e = e.Next() {
p := e.Value.(peer.ID)
pID := ConvertPeerID(p)
pd := peerDistance{
p: p,
distance: xor(target, pID),
}
peerArr = append(peerArr, &pd)
// Append the peer.ID values in the list to the sorter's slice. It may no longer be sorted.
func (pds *peerDistanceSorter) appendPeersFromList(l *list.List) {
for e := l.Front(); e != nil; e = e.Next() {
pds.appendPeer(e.Value.(peer.ID))
}
return peerArr
}

func (pds *peerDistanceSorter) sort() {
sort.Sort(pds)
}

// Sort the given peers by their ascending distance from the target. A new slice is returned.
func SortClosestPeers(peers []peer.ID, target ID) []peer.ID {
psarr := make(peerSorterArr, 0, len(peers))
sorter := peerDistanceSorter{
peers: make([]peerDistance, 0, len(peers)),
target: target,
}
for _, p := range peers {
pID := ConvertPeerID(p)
pd := &peerDistance{
p: p,
distance: xor(target, pID),
}
psarr = append(psarr, pd)
sorter.appendPeer(p)
}
sort.Sort(psarr)
out := make([]peer.ID, 0, len(psarr))
for _, p := range psarr {
sorter.sort()
out := make([]peer.ID, 0, sorter.Len())
for _, p := range sorter.peers {
out = append(out, p.p)
}
return out
Expand Down
28 changes: 14 additions & 14 deletions table.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package kbucket
import (
"errors"
"fmt"
"sort"
"sync"
"time"

Expand Down Expand Up @@ -169,6 +168,7 @@ func (rt *RoutingTable) NearestPeer(id ID) peer.ID {
func (rt *RoutingTable) NearestPeers(id ID, count int) []peer.ID {
cpl := CommonPrefixLen(id, rt.local)

// It's assumed that this also protects the buckets.
rt.tabLock.RLock()

// Get bucket at cpl index or last bucket
Expand All @@ -178,32 +178,32 @@ func (rt *RoutingTable) NearestPeers(id ID, count int) []peer.ID {
}
bucket = rt.Buckets[cpl]

peerArr := make(peerSorterArr, 0, count)
peerArr = copyPeersFromList(id, peerArr, bucket.list)
if len(peerArr) < count {
pds := peerDistanceSorter{
peers: make([]peerDistance, 0, 3*rt.bucketsize),
target: id,
}
pds.appendPeersFromList(bucket.list)
if pds.Len() < count {
// In the case of an unusual split, one bucket may be short or empty.
// if this happens, search both surrounding buckets for nearby peers
if cpl > 0 {
plist := rt.Buckets[cpl-1].list
peerArr = copyPeersFromList(id, peerArr, plist)
pds.appendPeersFromList(rt.Buckets[cpl-1].list)
}

if cpl < len(rt.Buckets)-1 {
plist := rt.Buckets[cpl+1].list
peerArr = copyPeersFromList(id, peerArr, plist)
pds.appendPeersFromList(rt.Buckets[cpl+1].list)
}
}
rt.tabLock.RUnlock()

// Sort by distance to local peer
sort.Sort(peerArr)
pds.sort()

if count < len(peerArr) {
peerArr = peerArr[:count]
if count < pds.Len() {
pds.peers = pds.peers[:count]
}

out := make([]peer.ID, 0, len(peerArr))
for _, p := range peerArr {
out := make([]peer.ID, 0, pds.Len())
for _, p := range pds.peers {
out = append(out, p.p)
}

Expand Down