Avoid reflection sorting request pieces

This commit is contained in:
Matt Joiner 2021-11-30 21:31:32 +11:00
parent de2bea502c
commit b99dd505b5
1 changed files with 54 additions and 22 deletions

View File

@ -43,25 +43,37 @@ func equalFilterPieces(l, r []filterPiece) bool {
return true return true
} }
func sortFilterPieces(pieces []filterPiece, indices []int) { type pieceSorter struct {
sort.Slice(indices, func(_i, _j int) bool { swap func(i, j int)
i := &pieces[indices[_i]] get func(i int) *filterPiece
j := &pieces[indices[_j]] len int
return multiless.New().Int( }
int(j.Priority), int(i.Priority),
).Bool( func (me pieceSorter) Len() int {
j.Partial, i.Partial, return me.len
).Int64( }
i.Availability, j.Availability,
).Int( func (me pieceSorter) Swap(i, j int) {
i.index, j.index, me.swap(i, j)
).Lazy(func() multiless.Computation { }
return multiless.New().Cmp(bytes.Compare(
i.t.InfoHash[:], func (me pieceSorter) Less(_i, _j int) bool {
j.t.InfoHash[:], i := me.get(_i)
)) j := me.get(_j)
}).MustLess() return multiless.New().Int(
}) int(j.Priority), int(i.Priority),
).Bool(
j.Partial, i.Partial,
).Int64(
i.Availability, j.Availability,
).Int(
i.index, j.index,
).Lazy(func() multiless.Computation {
return multiless.New().Cmp(bytes.Compare(
i.t.InfoHash[:],
j.t.InfoHash[:],
))
}).MustLess()
} }
type requestsPeer struct { type requestsPeer struct {
@ -124,6 +136,19 @@ func reorderedFilterPieces(pieces []filterPiece, indices []int) (ret []filterPie
var packageExpvarMap = expvar.NewMap("request-strategy") var packageExpvarMap = expvar.NewMap("request-strategy")
func getSortedFilterPieces(unsorted []filterPiece) []filterPiece { func getSortedFilterPieces(unsorted []filterPiece) []filterPiece {
const cachePieceSorts = false
if !cachePieceSorts {
sort.Sort(pieceSorter{
len: len(unsorted),
swap: func(i, j int) {
unsorted[i], unsorted[j] = unsorted[j], unsorted[i]
},
get: func(i int) *filterPiece {
return &unsorted[i]
},
})
return unsorted
}
sortsMu.Lock() sortsMu.Lock()
defer sortsMu.Unlock() defer sortsMu.Unlock()
for key, order := range sorts { for key, order := range sorts {
@ -132,12 +157,19 @@ func getSortedFilterPieces(unsorted []filterPiece) []filterPiece {
return reorderedFilterPieces(unsorted, order) return reorderedFilterPieces(unsorted, order)
} }
} }
sorted := append(make([]filterPiece, 0, len(unsorted)), unsorted...) indices := make([]int, len(unsorted))
indices := make([]int, len(sorted))
for i := 0; i < len(indices); i++ { for i := 0; i < len(indices); i++ {
indices[i] = i indices[i] = i
} }
sortFilterPieces(sorted, indices) sort.Sort(pieceSorter{
len: len(unsorted),
swap: func(i, j int) {
indices[i], indices[j] = indices[j], indices[i]
},
get: func(i int) *filterPiece {
return &unsorted[indices[i]]
},
})
packageExpvarMap.Add("added filter piece ordering", 1) packageExpvarMap.Add("added filter piece ordering", 1)
sorts[&unsorted] = indices sorts[&unsorted] = indices
runtime.SetFinalizer(&pieceOrderingFinalizer{unsorted: &unsorted}, func(me *pieceOrderingFinalizer) { runtime.SetFinalizer(&pieceOrderingFinalizer{unsorted: &unsorted}, func(me *pieceOrderingFinalizer) {