]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Allow some overlap between piece prioritization classes
authorMatt Joiner <anacrolix@gmail.com>
Thu, 19 Mar 2015 23:52:55 +0000 (10:52 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 19 Mar 2015 23:52:55 +0000 (10:52 +1100)
This probabilistically improves download speeds when doing readaheads

connection.go
connection_test.go

index 756729ae206568e7a0baa057e0c0b666870c6777..675ba57a078d681ccc6ca436362de70cc34e262a 100644 (file)
@@ -100,20 +100,23 @@ func (cn *connection) pendPiece(piece int, priority piecePriority) {
                cn.pieceRequestOrder.DeletePiece(piece)
                return
        }
-       key := cn.piecePriorities[piece]
-       // There is overlap here so there's some probabilistic favouring of higher
-       // priority pieces.
-       switch priority {
-       case piecePriorityReadahead:
-               key -= len(cn.piecePriorities)
-       case piecePriorityNext:
-               key -= 2 * len(cn.piecePriorities)
-       case piecePriorityNow:
-               key -= 3 * len(cn.piecePriorities)
-       }
-       // Favour earlier pieces more than later pieces.
-       // key -= piece / 2
-
+       pp := cn.piecePriorities[piece]
+       // Priority goes to Now, then Next in connection order. Then Readahead in
+       // by piece index. Then normal again by connection order.
+       key := func() int {
+               switch priority {
+               case piecePriorityNow:
+                       return -3*len(cn.piecePriorities) + 3*pp
+               case piecePriorityNext:
+                       return -2*len(cn.piecePriorities) + 2*pp
+               case piecePriorityReadahead:
+                       return -len(cn.piecePriorities) + pp
+               case piecePriorityNormal:
+                       return pp
+               default:
+                       panic(priority)
+               }
+       }()
        cn.pieceRequestOrder.SetPiece(piece, key)
 }
 
index 55181a9ca609bf2402f71ad405d00db109f7c1a1..ed26edec8fd68cef4f4358c6c69f4d53bc51f26e 100644 (file)
@@ -4,6 +4,8 @@ import (
        "testing"
        "time"
 
+       . "gopkg.in/check.v1"
+
        "github.com/bradfitz/iter"
 
        "bitbucket.org/anacrolix/go.torrent/internal/pieceordering"
@@ -53,21 +55,25 @@ func TestCancelRequestOptimized(t *testing.T) {
        }
 }
 
-func testRequestOrder(expected []int, ro *pieceordering.Instance, t *testing.T) {
-       e := ro.First()
-       for _, i := range expected {
-               if i != e.Piece() {
-                       t.FailNow()
-               }
-               e = e.Next()
-       }
-       if e != nil {
-               t.FailNow()
+func pieceOrderingAsSlice(po *pieceordering.Instance) (ret []int) {
+       for e := po.First(); e != nil; e = e.Next() {
+               ret = append(ret, e.Piece())
        }
+       return
+}
+
+func testRequestOrder(expected []int, ro *pieceordering.Instance, t *C) {
+       t.Assert(pieceOrderingAsSlice(ro), DeepEquals, expected)
 }
 
+type suite struct{}
+
+var _ = Suite(suite{})
+
+func Test(t *testing.T) { TestingT(t) }
+
 // Tests the request ordering based on a connections priorities.
-func TestPieceRequestOrder(t *testing.T) {
+func (suite) TestPieceRequestOrder(t *C) {
        c := connection{
                pieceRequestOrder: pieceordering.New(),
                piecePriorities:   []int{1, 4, 0, 3, 2},
@@ -83,10 +89,17 @@ func TestPieceRequestOrder(t *testing.T) {
        c.pendPiece(1, piecePriorityReadahead)
        testRequestOrder([]int{1, 2, 0}, c.pieceRequestOrder, t)
        c.pendPiece(4, piecePriorityNow)
+       // now(4), r(1), normal(0, 2)
        testRequestOrder([]int{4, 1, 2, 0}, c.pieceRequestOrder, t)
        c.pendPiece(2, piecePriorityReadahead)
        // N(4), R(1, 2), N(0)
-       testRequestOrder([]int{4, 1, 2, 0}, c.pieceRequestOrder, t)
+       testRequestOrder([]int{4, 2, 1, 0}, c.pieceRequestOrder, t)
+       c.pendPiece(1, piecePriorityNow)
+       // now(4, 1), readahead(2), normal(0)
+       // in the same order, the keys will be: -15+6, -15+12, -5, 1
+       // so we test that a very low priority (for this connection), "now"
+       // piece has been placed after a readahead piece.
+       testRequestOrder([]int{4, 2, 1, 0}, c.pieceRequestOrder, t)
        // Note this intentially sets to None a piece that's not in the order.
        for i := range iter.N(5) {
                c.pendPiece(i, piecePriorityNone)