]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Initialize connection piece priorities lazily, and using a pool
authorMatt Joiner <anacrolix@gmail.com>
Sat, 26 Sep 2015 07:27:35 +0000 (17:27 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Sat, 26 Sep 2015 07:27:35 +0000 (17:27 +1000)
client.go
connection.go
connection_test.go
torrent.go

index 559bcca9378efd44a0ac5fc67624ef398b6a511b..f11e892b81dad5ff136e378426a28a73ad1ad418 100644 (file)
--- a/client.go
+++ b/client.go
@@ -360,7 +360,7 @@ func (cl *Client) ConfigDir() string {
 }
 
 func (t *torrent) connPendPiece(c *connection, piece int) {
-       c.pendPiece(piece, t.Pieces[piece].Priority)
+       c.pendPiece(piece, t.Pieces[piece].Priority, t)
 }
 
 func (cl *Client) raisePiecePriority(t *torrent, piece int, priority piecePriority) {
@@ -1276,7 +1276,6 @@ func (t *torrent) initRequestOrdering(c *connection) {
        if c.pieceRequestOrder != nil || c.piecePriorities != nil {
                panic("double init of request ordering")
        }
-       c.piecePriorities = mathRand.Perm(t.numPieces())
        c.pieceRequestOrder = pieceordering.New()
        for i := range iter.N(t.Info.NumPieces()) {
                if !c.PeerHasPiece(i) {
@@ -1754,6 +1753,12 @@ func (me *Client) deleteConnection(t *torrent, c *connection) bool {
 func (me *Client) dropConnection(t *torrent, c *connection) {
        me.event.Broadcast()
        c.Close()
+       if c.piecePriorities != nil {
+               t.connPiecePriorites.Put(c.piecePriorities)
+               // I wonder if it's safe to set it to nil. Probably not. Since it's
+               // only read, it doesn't particularly matter if a closing connection
+               // shares the slice with another connection.
+       }
        if me.deleteConnection(t, c) {
                me.openNewConns(t)
        }
index 85df7eb47039228c6144fd0043c2859d8578c26f..bedb1a9b9209311b86fde72f849733cefaddeb8d 100644 (file)
@@ -105,11 +105,14 @@ func (cn *connection) localAddr() net.Addr {
 
 // Adjust piece position in the request order for this connection based on the
 // given piece priority.
-func (cn *connection) pendPiece(piece int, priority piecePriority) {
+func (cn *connection) pendPiece(piece int, priority piecePriority, t *torrent) {
        if priority == PiecePriorityNone {
                cn.pieceRequestOrder.DeletePiece(piece)
                return
        }
+       if cn.piecePriorities == nil {
+               cn.piecePriorities = t.newConnPiecePriorities()
+       }
        pp := cn.piecePriorities[piece]
        // Priority regions not to scale. Within each region, piece is randomized
        // according to connection.
index 3749a6ca68fc8cc1a4f28e9ff606b5d422468eb0..36832b9f1c93bb4b746ef540d419580c034a58fe 100644 (file)
@@ -71,22 +71,22 @@ func TestPieceRequestOrder(t *testing.T) {
                piecePriorities:   []int{1, 4, 0, 3, 2},
        }
        testRequestOrder(nil, c.pieceRequestOrder, t)
-       c.pendPiece(2, PiecePriorityNone)
+       c.pendPiece(2, PiecePriorityNone, nil)
        testRequestOrder(nil, c.pieceRequestOrder, t)
-       c.pendPiece(1, PiecePriorityNormal)
-       c.pendPiece(2, PiecePriorityNormal)
+       c.pendPiece(1, PiecePriorityNormal, nil)
+       c.pendPiece(2, PiecePriorityNormal, nil)
        testRequestOrder([]int{2, 1}, c.pieceRequestOrder, t)
-       c.pendPiece(0, PiecePriorityNormal)
+       c.pendPiece(0, PiecePriorityNormal, nil)
        testRequestOrder([]int{2, 0, 1}, c.pieceRequestOrder, t)
-       c.pendPiece(1, PiecePriorityReadahead)
+       c.pendPiece(1, PiecePriorityReadahead, nil)
        testRequestOrder([]int{1, 2, 0}, c.pieceRequestOrder, t)
-       c.pendPiece(4, PiecePriorityNow)
+       c.pendPiece(4, PiecePriorityNow, nil)
        // now(4), r(1), normal(0, 2)
        testRequestOrder([]int{4, 1, 2, 0}, c.pieceRequestOrder, t)
-       c.pendPiece(2, PiecePriorityReadahead)
+       c.pendPiece(2, PiecePriorityReadahead, nil)
        // N(4), R(1, 2), N(0)
        testRequestOrder([]int{4, 2, 1, 0}, c.pieceRequestOrder, t)
-       c.pendPiece(1, PiecePriorityNow)
+       c.pendPiece(1, PiecePriorityNow, nil)
        // 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"
@@ -94,7 +94,7 @@ func TestPieceRequestOrder(t *testing.T) {
        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)
+               c.pendPiece(i, PiecePriorityNone, nil)
        }
        testRequestOrder(nil, c.pieceRequestOrder, t)
 }
index 6498c23ec99fa70795e5290718e66c1590ca29e5..79a6a1599aedf76501eea19ae2c7cc3693ec3483 100644 (file)
@@ -2,9 +2,11 @@ package torrent
 
 import (
        "container/heap"
+       "expvar"
        "fmt"
        "io"
        "log"
+       "math/rand"
        "net"
        "sort"
        "sync"
@@ -102,6 +104,23 @@ type torrent struct {
 
        // Closed when .Info is set.
        gotMetainfo chan struct{}
+
+       connPiecePriorites sync.Pool
+}
+
+var (
+       piecePrioritiesReused = expvar.NewInt("piecePrioritiesReused")
+       piecePrioritiesNew    = expvar.NewInt("piecePrioritiesNew")
+)
+
+func (t *torrent) newConnPiecePriorities() []int {
+       _ret := t.connPiecePriorites.Get()
+       if _ret != nil {
+               piecePrioritiesReused.Add(1)
+               return _ret.([]int)
+       }
+       piecePrioritiesNew.Add(1)
+       return rand.Perm(t.numPieces())
 }
 
 func (t *torrent) pieceComplete(piece int) bool {