Commit e2034eb9 authored by Janoš Guljaš's avatar Janoš Guljaš Committed by GitHub

perf(pslice): optimize Add method (#1824)

parent dd605e23
...@@ -173,12 +173,9 @@ func (s *PSlice) Add(addr swarm.Address, po uint8) { ...@@ -173,12 +173,9 @@ func (s *PSlice) Add(addr swarm.Address, po uint8) {
return return
} }
peers, bins := s.copy() peers, bins := s.copy(1)
head := peers[:s.bins[po]] peers = insertAddresses(peers, int(s.bins[po]), addr)
tail := append([]swarm.Address{addr}, peers[s.bins[po]:]...)
peers = append(head, tail...)
s.peers = peers s.peers = peers
incDeeper(bins, po) incDeeper(bins, po)
...@@ -195,7 +192,7 @@ func (s *PSlice) Remove(addr swarm.Address, po uint8) { ...@@ -195,7 +192,7 @@ func (s *PSlice) Remove(addr swarm.Address, po uint8) {
return return
} }
peers, bins := s.copy() peers, bins := s.copy(0)
peers = append(peers[:i], peers[i+1:]...) peers = append(peers[:i], peers[i+1:]...)
s.peers = peers s.peers = peers
...@@ -231,10 +228,29 @@ func decDeeper(bins []uint, po uint8) { ...@@ -231,10 +228,29 @@ func decDeeper(bins []uint, po uint8) {
} }
} }
func (s *PSlice) copy() (peers []swarm.Address, bins []uint) { // copy makes copies of peers and bins with a possibility of adding peers
peers = make([]swarm.Address, len(s.peers)) // additional capacity if it is know that a number of new addresses will be
// inserted.
func (s *PSlice) copy(peersExtraCap int) (peers []swarm.Address, bins []uint) {
peers = make([]swarm.Address, len(s.peers), len(s.peers)+peersExtraCap)
copy(peers, s.peers) copy(peers, s.peers)
bins = make([]uint, len(s.bins)) bins = make([]uint, len(s.bins))
copy(bins, s.bins) copy(bins, s.bins)
return peers, bins return peers, bins
} }
// insertAddresses is based on the optimized implementation from
// https://github.com/golang/go/wiki/SliceTricks#insertvector
func insertAddresses(s []swarm.Address, pos int, vs ...swarm.Address) []swarm.Address {
if n := len(s) + len(vs); n <= cap(s) {
s2 := s[:n]
copy(s2[pos+len(vs):], s[pos:])
copy(s2[pos:], vs)
return s2
}
s2 := make([]swarm.Address, len(s)+len(vs))
copy(s2, s[:pos])
copy(s2[pos:], vs)
copy(s2[pos+len(vs):], s[pos:])
return s2
}
...@@ -413,3 +413,23 @@ func chkNotExists(t *testing.T, ps *pslice.PSlice, addrs ...swarm.Address) { ...@@ -413,3 +413,23 @@ func chkNotExists(t *testing.T, ps *pslice.PSlice, addrs ...swarm.Address) {
} }
} }
} }
func BenchmarkAdd(b *testing.B) {
var (
ps = pslice.New(16)
base = test.RandomAddress()
)
for i := 0; i < 16; i++ {
for j := 0; j < 300; j++ {
ps.Add(test.RandomAddressAt(base, i), uint8(i))
}
}
const po = 8
b.ResetTimer()
for n := 0; n < b.N; n++ {
ps.Add(test.RandomAddressAt(base, po), po)
}
}
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