]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Avoid reflection sorting request pieces
authorMatt Joiner <anacrolix@gmail.com>
Tue, 30 Nov 2021 10:31:32 +0000 (21:31 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Sun, 12 Dec 2021 07:35:01 +0000 (18:35 +1100)
request-strategy/order.go

index e6cf7dc02c898dacacb018e319399f3b9dd45dc4..91dfc74d8f5603f045a406754798131e32c6069c 100644 (file)
@@ -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) {