requesting.go | 14 ++++++++------ torrent.go | 5 +++++ diff --git a/requesting.go b/requesting.go index 3c204b843cb5e6ec0431e219f01076874243079e..98e9e88bf34048a6ae8ec6ddaaaefd49c8a9dc02 100644 --- a/requesting.go +++ b/requesting.go @@ -70,7 +70,7 @@ type desiredPeerRequests struct { requestIndexes []RequestIndex peer *Peer - pieceStates map[pieceIndex]request_strategy.PieceRequestOrderState + pieceStates []request_strategy.PieceRequestOrderState } func (p *desiredPeerRequests) Len() int { @@ -95,8 +95,8 @@ !p.peer.peerAllowedFast.Contains(leftPieceIndex), !p.peer.peerAllowedFast.Contains(rightPieceIndex), ) } - leftPiece := p.pieceStates[leftPieceIndex] - rightPiece := p.pieceStates[rightPieceIndex] + leftPiece := &p.pieceStates[leftPieceIndex] + rightPiece := &p.pieceStates[rightPieceIndex] // Putting this first means we can steal requests from lesser-performing peers for our first few // new requests. priority := func() piecePriority { @@ -193,8 +193,9 @@ return } input := t.getRequestStrategyInput() requestHeap := desiredPeerRequests{ - peer: p, - pieceStates: make(map[pieceIndex]request_strategy.PieceRequestOrderState), + peer: p, + pieceStates: t.requestPieceStates, + requestIndexes: t.requestIndexes, } request_strategy.GetRequestablePieces( input, @@ -206,6 +207,7 @@ } if !p.peerHasPiece(pieceIndex) { return } + requestHeap.pieceStates[pieceIndex] = pieceExtra allowedFast := p.peerAllowedFast.Contains(pieceIndex) p.t.piece(pieceIndex).undirtiedChunksIter.Iter(func(ci request_strategy.ChunkIndex) { r := p.t.pieceRequestIndexOffset(pieceIndex) + ci @@ -228,7 +230,6 @@ // Can't re-request while awaiting acknowledgement. return } requestHeap.requestIndexes = append(requestHeap.requestIndexes, r) - requestHeap.pieceStates[pieceIndex] = pieceExtra }) }, ) @@ -256,6 +257,7 @@ pprof.Labels("update request", p.needRequestUpdate), func(_ context.Context) { next := p.getDesiredRequestState() p.applyRequestState(next) + p.t.requestIndexes = next.Requests.requestIndexes[:0] }, ) } diff --git a/torrent.go b/torrent.go index 4f06d6501a9c02e3662e8b36ac665317a696ecfc..dbfbea18ef2a5d8998bd283605724e5eefd325e6 100644 --- a/torrent.go +++ b/torrent.go @@ -157,6 +157,10 @@ activeSources sync.Map sourcesLogger log.Logger smartBanCache smartBanCache + + // Large allocations reused between request state updates. + requestPieceStates []request_strategy.PieceRequestOrderState + requestIndexes []RequestIndex } func (t *Torrent) selectivePieceAvailabilityFromPeers(i pieceIndex) (count int) { @@ -457,6 +461,7 @@ // This seems to be all the follow-up tasks after info is set, that can't fail. func (t *Torrent) onSetInfo() { t.initPieceRequestOrder() MakeSliceWithLength(&t.requestState, t.numChunks()) + MakeSliceWithLength(&t.requestPieceStates, t.numPieces()) for i := range t.pieces { p := &t.pieces[i] // Need to add relativeAvailability before updating piece completion, as that may result in conns