From b99dd505b5745e51f5782a0318f8067e6235e930 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Tue, 30 Nov 2021 21:31:32 +1100 Subject: [PATCH] Avoid reflection sorting request pieces --- request-strategy/order.go | 76 +++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/request-strategy/order.go b/request-strategy/order.go index e6cf7dc0..91dfc74d 100644 --- a/request-strategy/order.go +++ b/request-strategy/order.go @@ -43,25 +43,37 @@ func equalFilterPieces(l, r []filterPiece) bool { return true } -func sortFilterPieces(pieces []filterPiece, indices []int) { - sort.Slice(indices, func(_i, _j int) bool { - i := &pieces[indices[_i]] - j := &pieces[indices[_j]] - 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 pieceSorter struct { + swap func(i, j int) + get func(i int) *filterPiece + len int +} + +func (me pieceSorter) Len() int { + return me.len +} + +func (me pieceSorter) Swap(i, j int) { + me.swap(i, j) +} + +func (me pieceSorter) Less(_i, _j int) bool { + i := me.get(_i) + j := me.get(_j) + 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 { @@ -124,6 +136,19 @@ func reorderedFilterPieces(pieces []filterPiece, indices []int) (ret []filterPie var packageExpvarMap = expvar.NewMap("request-strategy") 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() defer sortsMu.Unlock() for key, order := range sorts { @@ -132,12 +157,19 @@ func getSortedFilterPieces(unsorted []filterPiece) []filterPiece { return reorderedFilterPieces(unsorted, order) } } - sorted := append(make([]filterPiece, 0, len(unsorted)), unsorted...) - indices := make([]int, len(sorted)) + indices := make([]int, len(unsorted)) for i := 0; i < len(indices); 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) sorts[&unsorted] = indices runtime.SetFinalizer(&pieceOrderingFinalizer{unsorted: &unsorted}, func(me *pieceOrderingFinalizer) {