When Reader position changes only update piece priorities that may be affected
Seems to significantly reduce CPU load reading from torrents with huge piece counts.
This commit is contained in:
parent
95f73db7e4
commit
a8e96ce996
11
reader.go
11
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) {
|
||||
|
|
2
t.go
2
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) {
|
||||
|
|
38
torrent.go
38
torrent.go
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ func BenchmarkUpdatePiecePriorities(b *testing.B) {
|
|||
t.completedPieces.Set(i, true)
|
||||
}
|
||||
for range iter.N(b.N) {
|
||||
t.updatePiecePriorities()
|
||||
t.updateAllPiecePriorities()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue