From: Matt Joiner Date: Thu, 8 Feb 2024 06:58:12 +0000 (+1100) Subject: Restore request strategy Torrent.Piece use, without a heap allocation X-Git-Tag: v1.54.0~5 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=0f46fc993fc0007855bcf72143e9187922bef2a3;p=btrtrc.git Restore request strategy Torrent.Piece use, without a heap allocation --- diff --git a/request-strategy-impls.go b/request-strategy-impls.go index 0b05ed41..5d91e64a 100644 --- a/request-strategy-impls.go +++ b/request-strategy-impls.go @@ -44,15 +44,8 @@ type requestStrategyTorrent struct { t *Torrent } -func (r requestStrategyTorrent) IgnorePiece(i int) bool { - if r.t.ignorePieceForRequests(i) { - return true - } - if r.t.pieceNumPendingChunks(i) == 0 { - return true - } - - return false +func (r requestStrategyTorrent) Piece(i int) request_strategy.Piece { + return (*requestStrategyPiece)(r.t.piece(i)) } func (r requestStrategyTorrent) PieceLength() int64 { @@ -61,17 +54,14 @@ func (r requestStrategyTorrent) PieceLength() int64 { var _ request_strategy.Torrent = requestStrategyTorrent{} -type requestStrategyPiece struct { - t *Torrent - i pieceIndex -} +type requestStrategyPiece Piece -func (r requestStrategyPiece) Request() bool { - return !r.t.ignorePieceForRequests(r.i) +func (r *requestStrategyPiece) Request() bool { + return !r.t.ignorePieceForRequests(r.index) } -func (r requestStrategyPiece) NumPendingChunks() int { - return int(r.t.pieceNumPendingChunks(r.i)) +func (r *requestStrategyPiece) NumPendingChunks() int { + return int(r.t.pieceNumPendingChunks(r.index)) } -var _ request_strategy.Piece = requestStrategyPiece{} +var _ request_strategy.Piece = (*requestStrategyPiece)(nil) diff --git a/request-strategy-impls_test.go b/request-strategy-impls_test.go new file mode 100644 index 00000000..f0d3fa18 --- /dev/null +++ b/request-strategy-impls_test.go @@ -0,0 +1,29 @@ +package torrent + +import ( + "io" + "runtime" + "testing" + + "github.com/davecgh/go-spew/spew" + qt "github.com/frankban/quicktest" + + request_strategy "github.com/anacrolix/torrent/request-strategy" +) + +func makeRequestStrategyPiece(t request_strategy.Torrent) request_strategy.Piece { + return t.Piece(0) +} + +func TestRequestStrategyPieceDoesntAlloc(t *testing.T) { + c := qt.New(t) + akshalTorrent := &Torrent{pieces: make([]Piece, 1)} + rst := requestStrategyTorrent{akshalTorrent} + var before, after runtime.MemStats + runtime.ReadMemStats(&before) + p := makeRequestStrategyPiece(rst) + runtime.ReadMemStats(&after) + c.Assert(before.HeapAlloc, qt.Equals, after.HeapAlloc) + // We have to use p, or it gets optimized away. + spew.Fdump(io.Discard, p) +} diff --git a/request-strategy/order.go b/request-strategy/order.go index df656f6d..92793f58 100644 --- a/request-strategy/order.go +++ b/request-strategy/order.go @@ -66,7 +66,8 @@ func GetRequestablePieces( lastItem.Set(_i) ih := _i.key.InfoHash - t := input.Torrent(ih) + var t Torrent = input.Torrent(ih) + var piece Piece = t.Piece(_i.key.Index) pieceLength := t.PieceLength() if storageLeft != nil { if *storageLeft < pieceLength { @@ -74,7 +75,7 @@ func GetRequestablePieces( } *storageLeft -= pieceLength } - if t.IgnorePiece(_i.key.Index) { + if !piece.Request() || piece.NumPendingChunks() == 0 { // TODO: Clarify exactly what is verified. Stuff that's being hashed should be // considered unverified and hold up further requests. return true diff --git a/request-strategy/torrent.go b/request-strategy/torrent.go index 5bc438ee..690f8b6d 100644 --- a/request-strategy/torrent.go +++ b/request-strategy/torrent.go @@ -1,6 +1,6 @@ package requestStrategy type Torrent interface { - IgnorePiece(int) bool + Piece(int) Piece PieceLength() int64 }