From 26116a7df83fbc8ede9b31354d025359ddf7feba Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Thu, 29 May 2014 01:32:34 +1000 Subject: [PATCH] Shuffle chunk spec request order for readahead pieces Should reduce overlap in received chunks. --- client.go | 6 ++++-- misc.go | 15 ++++++++++++++- torrent.go | 4 ++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index e079881a..e86a93a9 100644 --- a/client.go +++ b/client.go @@ -819,8 +819,10 @@ func (me *ResponsiveDownloadStrategy) FillRequests(t *torrent, c *connection) { if t.PieceNumPendingBytes(index) == t.PieceLength(index) { break } - for chunkSpec := range t.Pieces[index].PendingChunkSpecs { - if !c.Request(request{index, chunkSpec}) { + // Request chunks in random order to reduce overlap with other + // connections. + for _, cs := range t.Pieces[index].shuffledPendingChunkSpecs() { + if !c.Request(request{index, cs}) { return } } diff --git a/misc.go b/misc.go index 2e5f02bb..c53976fa 100644 --- a/misc.go +++ b/misc.go @@ -4,6 +4,7 @@ import ( "bitbucket.org/anacrolix/go.torrent/mmap_span" "crypto" "errors" + "math/rand" "os" "path/filepath" "time" @@ -15,7 +16,7 @@ import ( const ( pieceHash = crypto.SHA1 - maxRequests = 250 // Maximum pending requests we allow peers to send us. + maxRequests = 250 // Maximum pending requests we allow peers to send us. chunkSize = 0x4000 // 16KiB BEP20 = "-GT0000-" // Peer ID client identifier prefix dialTimeout = time.Second * 15 @@ -46,6 +47,18 @@ type piece struct { EverHashed bool } +func (p *piece) shuffledPendingChunkSpecs() (css []chunkSpec) { + css = make([]chunkSpec, 0, len(p.PendingChunkSpecs)) + for cs := range p.PendingChunkSpecs { + css = append(css, cs) + } + for i := range css { + j := rand.Intn(i + 1) + css[i], css[j] = css[j], css[i] + } + return +} + func (p *piece) Complete() bool { return len(p.PendingChunkSpecs) == 0 && p.EverHashed } diff --git a/torrent.go b/torrent.go index dfe24314..cbb4cd32 100644 --- a/torrent.go +++ b/torrent.go @@ -59,6 +59,10 @@ func (t *torrent) ChunkCount() (num int) { return } +func (t *torrent) UsualPieceSize() int { + return int(t.MetaInfo.PieceLength) +} + func (t *torrent) LastPieceSize() int { return int(t.PieceLength(pp.Integer(t.NumPieces() - 1))) } -- 2.48.1