Avoid heap allocation in GetRequestablePieces (#734)

The calculation of whether we should ignore a piece in
GetRequestablePieces ends up doing an allocation for every piece, when
all we really need to do is query the index in the torrent. Provide an
IgnorePiece function instead, which avoids the need for a temporary
allocation.

Observed to cut out 40% of object allocations in some workloads (large
download, lots of seeds).
This commit is contained in:
Jonathan McDowell 2022-04-11 05:22:05 +01:00 committed by GitHub
parent cba434999a
commit a1a820d3c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 11 additions and 5 deletions

View File

@ -44,8 +44,15 @@ type requestStrategyTorrent struct {
t *Torrent t *Torrent
} }
func (r requestStrategyTorrent) Piece(i int) request_strategy.Piece { func (r requestStrategyTorrent) IgnorePiece(i int) bool {
return requestStrategyPiece{r.t, i} if r.t.ignorePieceForRequests(i) {
return true
}
if r.t.pieceNumPendingChunks(i) == 0 {
return true
}
return false
} }
func (r requestStrategyTorrent) ChunksPerPiece() uint32 { func (r requestStrategyTorrent) ChunksPerPiece() uint32 {

View File

@ -54,7 +54,6 @@ func GetRequestablePieces(input Input, pro *PieceRequestOrder, f func(ih metainf
pro.tree.Scan(func(_i pieceRequestOrderItem) bool { pro.tree.Scan(func(_i pieceRequestOrderItem) bool {
ih := _i.key.InfoHash ih := _i.key.InfoHash
var t Torrent = input.Torrent(ih) var t Torrent = input.Torrent(ih)
var piece Piece = t.Piece(_i.key.Index)
pieceLength := t.PieceLength() pieceLength := t.PieceLength()
if storageLeft != nil { if storageLeft != nil {
if *storageLeft < pieceLength { if *storageLeft < pieceLength {
@ -62,7 +61,7 @@ func GetRequestablePieces(input Input, pro *PieceRequestOrder, f func(ih metainf
} }
*storageLeft -= pieceLength *storageLeft -= pieceLength
} }
if !piece.Request() || piece.NumPendingChunks() == 0 { if t.IgnorePiece(_i.key.Index) {
// TODO: Clarify exactly what is verified. Stuff that's being hashed should be // TODO: Clarify exactly what is verified. Stuff that's being hashed should be
// considered unverified and hold up further requests. // considered unverified and hold up further requests.
return true return true

View File

@ -1,7 +1,7 @@
package request_strategy package request_strategy
type Torrent interface { type Torrent interface {
Piece(int) Piece IgnorePiece(int) bool
ChunksPerPiece() uint32 ChunksPerPiece() uint32
PieceLength() int64 PieceLength() int64
} }