]> Sergey Matveev's repositories - btrtrc.git/commitdiff
When Reader position changes only update piece priorities that may be affected
authorMatt Joiner <anacrolix@gmail.com>
Mon, 31 Oct 2016 08:00:08 +0000 (19:00 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 31 Oct 2016 08:00:08 +0000 (19:00 +1100)
Seems to significantly reduce CPU load reading from torrents with huge piece counts.

reader.go
t.go
torrent.go
torrent_test.go

index 3f22c6c656548c0804a2953b7bad8141d7de65ea..b3b6fd9be6ac099640770327fa0e45f9b6a88b0f 100644 (file)
--- a/reader.go
+++ b/reader.go
@@ -202,7 +202,7 @@ func (r *Reader) readOnceAt(b []byte, pos int64, ctxErr *error) (n int, err erro
                log.Printf("error reading torrent %q piece %d offset %d, %d bytes: %s", r.t, pi, po, len(b1), err)
                r.t.cl.mu.Lock()
                r.t.updateAllPieceCompletions()
-               r.t.updatePiecePriorities()
+               r.t.updateAllPiecePriorities()
                r.t.cl.mu.Unlock()
        }
 }
@@ -214,12 +214,13 @@ func (r *Reader) Close() error {
 }
 
 func (r *Reader) posChanged() {
-       p := r.piecesUncached()
-       if p == r.pieces {
+       to := r.piecesUncached()
+       from := r.pieces
+       if to == from {
                return
        }
-       r.pieces = p
-       r.t.readersChanged()
+       r.pieces = to
+       r.t.readerPosChanged(from, to)
 }
 
 func (r *Reader) Seek(off int64, whence int) (ret int64, err error) {
diff --git a/t.go b/t.go
index 138770ea7257566c4b40a191713580a17ac52253..b17226be9b16d7269564f31b1f84b25aa8cb8184 100644 (file)
--- a/t.go
+++ b/t.go
@@ -132,7 +132,7 @@ func (t *Torrent) addReader(r *Reader) {
                t.readers = make(map[*Reader]struct{})
        }
        t.readers[r] = struct{}{}
-       t.readersChanged()
+       r.posChanged()
 }
 
 func (t *Torrent) deleteReader(r *Reader) {
index c8514654c4751f7f00a1aad1fa467f6bb3f416e6..d53efb0acb96ec75fe4ebc17b84e9b53cb755cd2 100644 (file)
@@ -835,8 +835,36 @@ func (t *Torrent) forUrgentPieces(f func(piece int) (again bool)) (all bool) {
 }
 
 func (t *Torrent) readersChanged() {
+       t.updateReaderPieces()
+       t.updateAllPiecePriorities()
+}
+
+func (t *Torrent) updateReaderPieces() {
        t.readerNowPieces, t.readerReadaheadPieces = t.readerPiecePriorities()
-       t.updatePiecePriorities()
+}
+
+func (t *Torrent) readerPosChanged(from, to pieceRange) {
+       if from == to {
+               return
+       }
+       t.updateReaderPieces()
+       // Order the ranges, high and low.
+       l, h := from, to
+       if l.begin > h.begin {
+               l, h = h, l
+       }
+       if l.end < h.begin {
+               // Two distinct ranges.
+               t.updatePiecePriorities(l.begin, l.end)
+               t.updatePiecePriorities(h.begin, h.end)
+       } else {
+               // Ranges overlap.
+               end := l.end
+               if h.end > end {
+                       end = h.end
+               }
+               t.updatePiecePriorities(l.begin, end)
+       }
 }
 
 func (t *Torrent) maybeNewConns() {
@@ -863,10 +891,14 @@ func (t *Torrent) updatePiecePriority(piece int) {
        t.piecePriorityChanged(piece)
 }
 
+func (t *Torrent) updateAllPiecePriorities() {
+       t.updatePiecePriorities(0, len(t.pieces))
+}
+
 // Update all piece priorities in one hit. This function should have the same
 // output as updatePiecePriority, but across all pieces.
-func (t *Torrent) updatePiecePriorities() {
-       for i := range t.pieces {
+func (t *Torrent) updatePiecePriorities(begin, end int) {
+       for i := begin; i < end; i++ {
                t.updatePiecePriority(i)
        }
 }
index 0cf213ad20982f530455d746f09737c69f48c5ba..a0d0857c69ce972abd490202bdafa01accb59197 100644 (file)
@@ -92,7 +92,7 @@ func BenchmarkUpdatePiecePriorities(b *testing.B) {
                t.completedPieces.Set(i, true)
        }
        for range iter.N(b.N) {
-               t.updatePiecePriorities()
+               t.updateAllPiecePriorities()
        }
 }