Initialize connection piece priorities lazily, and using a pool
This commit is contained in:
parent
52b0705956
commit
53259397fc
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
19
torrent.go
19
torrent.go
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue