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:
Matt Joiner 2016-10-31 19:00:08 +11:00
parent 95f73db7e4
commit a8e96ce996
4 changed files with 43 additions and 10 deletions

View File

@ -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) 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.cl.mu.Lock()
r.t.updateAllPieceCompletions() r.t.updateAllPieceCompletions()
r.t.updatePiecePriorities() r.t.updateAllPiecePriorities()
r.t.cl.mu.Unlock() r.t.cl.mu.Unlock()
} }
} }
@ -214,12 +214,13 @@ func (r *Reader) Close() error {
} }
func (r *Reader) posChanged() { func (r *Reader) posChanged() {
p := r.piecesUncached() to := r.piecesUncached()
if p == r.pieces { from := r.pieces
if to == from {
return return
} }
r.pieces = p r.pieces = to
r.t.readersChanged() r.t.readerPosChanged(from, to)
} }
func (r *Reader) Seek(off int64, whence int) (ret int64, err error) { func (r *Reader) Seek(off int64, whence int) (ret int64, err error) {

2
t.go
View File

@ -132,7 +132,7 @@ func (t *Torrent) addReader(r *Reader) {
t.readers = make(map[*Reader]struct{}) t.readers = make(map[*Reader]struct{})
} }
t.readers[r] = struct{}{} t.readers[r] = struct{}{}
t.readersChanged() r.posChanged()
} }
func (t *Torrent) deleteReader(r *Reader) { func (t *Torrent) deleteReader(r *Reader) {

View File

@ -835,8 +835,36 @@ func (t *Torrent) forUrgentPieces(f func(piece int) (again bool)) (all bool) {
} }
func (t *Torrent) readersChanged() { func (t *Torrent) readersChanged() {
t.updateReaderPieces()
t.updateAllPiecePriorities()
}
func (t *Torrent) updateReaderPieces() {
t.readerNowPieces, t.readerReadaheadPieces = t.readerPiecePriorities() 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() { func (t *Torrent) maybeNewConns() {
@ -863,10 +891,14 @@ func (t *Torrent) updatePiecePriority(piece int) {
t.piecePriorityChanged(piece) 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 // Update all piece priorities in one hit. This function should have the same
// output as updatePiecePriority, but across all pieces. // output as updatePiecePriority, but across all pieces.
func (t *Torrent) updatePiecePriorities() { func (t *Torrent) updatePiecePriorities(begin, end int) {
for i := range t.pieces { for i := begin; i < end; i++ {
t.updatePiecePriority(i) t.updatePiecePriority(i)
} }
} }

View File

@ -92,7 +92,7 @@ func BenchmarkUpdatePiecePriorities(b *testing.B) {
t.completedPieces.Set(i, true) t.completedPieces.Set(i, true)
} }
for range iter.N(b.N) { for range iter.N(b.N) {
t.updatePiecePriorities() t.updateAllPiecePriorities()
} }
} }