diff --git a/core/network/network.go b/core/network/network.go index 13c24ff2ff..7691c333b1 100644 --- a/core/network/network.go +++ b/core/network/network.go @@ -9,9 +9,10 @@ import ( "bytes" "context" "io" - "sort" "time" + "golang.org/x/exp/slices" + "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" @@ -203,7 +204,8 @@ func DedupAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { if len(addrs) == 0 { return addrs } - sort.Slice(addrs, func(i, j int) bool { return bytes.Compare(addrs[i].Bytes(), addrs[j].Bytes()) < 0 }) + // Use the new slices package here, as the sort function doesn't allocate (sort.Slice does). + slices.SortFunc(addrs, func(a, b ma.Multiaddr) bool { return bytes.Compare(a.Bytes(), b.Bytes()) < 0 }) idx := 1 for i := 1; i < len(addrs); i++ { if !addrs[i-1].Equal(addrs[i]) { diff --git a/core/network/network_test.go b/core/network/network_test.go index a78e6d7044..472acb0341 100644 --- a/core/network/network_test.go +++ b/core/network/network_test.go @@ -2,6 +2,8 @@ package network import ( "fmt" + "math" + "math/rand" "testing" ma "github.com/multiformats/go-multiaddr" @@ -34,3 +36,24 @@ func TestDedupAddrs(t *testing.T) { }) } } + +func BenchmarkDedupAddrs(b *testing.B) { + b.ReportAllocs() + var addrs []ma.Multiaddr + r := rand.New(rand.NewSource(1234)) + for i := 0; i < 100; i++ { + tcpAddr := ma.StringCast(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", r.Intn(math.MaxUint16))) + quicAddr := ma.StringCast(fmt.Sprintf("/ip4/127.0.0.1/udp/%d/quic-v1", r.Intn(math.MaxUint16))) + wsAddr := ma.StringCast(fmt.Sprintf("/ip4/127.0.0.1/tcp/%d/ws", r.Intn(math.MaxUint16))) + addrs = append(addrs, tcpAddr, tcpAddr, quicAddr, quicAddr, wsAddr) + } + for _, sz := range []int{10, 20, 30, 50, 100} { + b.Run(fmt.Sprintf("%d", sz), func(b *testing.B) { + items := make([]ma.Multiaddr, sz) + for i := 0; i < b.N; i++ { + copy(items, addrs[:sz]) + DedupAddrs(items) + } + }) + } +}