From f9ed9c4c04782e14663ef0b04ffe25ea6f6cef4f Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Sun, 20 Sep 2015 11:29:52 +1000 Subject: [PATCH] Avoid frequent allocation of piece request order iterator --- internal/pieceordering/pieceordering.go | 8 +++-- internal/pieceordering/pieceordering_test.go | 35 ++++++++++++++++++-- torrent.go | 2 +- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/internal/pieceordering/pieceordering.go b/internal/pieceordering/pieceordering.go index 169ebbc7..4c4226b0 100644 --- a/internal/pieceordering/pieceordering.go +++ b/internal/pieceordering/pieceordering.go @@ -89,7 +89,7 @@ func (me *Instance) DeletePiece(piece int) { } // Returns the piece with the lowest key. -func (me Instance) First() Element { +func (me *Instance) First() Element { i := me.sl.SeekToFirst() if i == nil { return nil @@ -97,6 +97,10 @@ func (me Instance) First() Element { return &element{i, i.Value().([]int)} } +func (me *Instance) Empty() bool { + return me.sl.Len() == 0 +} + type Element interface { Piece() int Next() Element @@ -120,6 +124,6 @@ func (e *element) Next() Element { return e } -func (e element) Piece() int { +func (e *element) Piece() int { return e.sl[0] } diff --git a/internal/pieceordering/pieceordering_test.go b/internal/pieceordering/pieceordering_test.go index b2b19e11..d72b5052 100644 --- a/internal/pieceordering/pieceordering_test.go +++ b/internal/pieceordering/pieceordering_test.go @@ -3,6 +3,9 @@ package pieceordering import ( "sort" "testing" + + "github.com/bradfitz/iter" + "github.com/stretchr/testify/assert" ) func instanceSlice(i *Instance) (sl []int) { @@ -26,7 +29,7 @@ func sameContents(a, b []int) bool { return true } -func checkOrder(t *testing.T, i *Instance, ppp ...[]int) { +func checkOrder(t testing.TB, i *Instance, ppp ...[]int) { fatal := func() { t.Fatalf("have %v, expected %v", instanceSlice(i), ppp) } @@ -46,9 +49,11 @@ func checkOrder(t *testing.T, i *Instance, ppp ...[]int) { } } -func TestPieceOrdering(t *testing.T) { +func testPieceOrdering(t testing.TB) { i := New() + assert.True(t, i.Empty()) i.SetPiece(0, 1) + assert.False(t, i.Empty()) i.SetPiece(1, 0) checkOrder(t, i, []int{1, 0}) i.SetPiece(1, 2) @@ -59,8 +64,10 @@ func TestPieceOrdering(t *testing.T) { i.DeletePiece(1) checkOrder(t, i, []int{0}) i.DeletePiece(0) + assert.True(t, i.Empty()) checkOrder(t, i, nil) i.SetPiece(2, 1) + assert.False(t, i.Empty()) i.SetPiece(1, 1) i.SetPiece(3, 1) checkOrder(t, i, []int{3, 1, 2}) @@ -70,9 +77,33 @@ func TestPieceOrdering(t *testing.T) { i.DeletePiece(2) i.DeletePiece(3) i.DeletePiece(1) + assert.True(t, i.Empty()) checkOrder(t, i, nil) + // Deleting pieces that aren't present. i.DeletePiece(2) i.DeletePiece(3) i.DeletePiece(1) + assert.True(t, i.Empty()) checkOrder(t, i, nil) } + +func TestPieceOrdering(t *testing.T) { + testPieceOrdering(t) +} + +func BenchmarkPieceOrdering(b *testing.B) { + for range iter.N(b.N) { + testPieceOrdering(b) + } +} + +func BenchmarkIteration(b *testing.B) { + for range iter.N(b.N) { + i := New() + for p := range iter.N(500) { + i.SetPiece(p, p) + } + for e := i.First(); e != nil; e = e.Next() { + } + } +} diff --git a/torrent.go b/torrent.go index b0c607b0..a9431a38 100644 --- a/torrent.go +++ b/torrent.go @@ -738,7 +738,7 @@ func (t *torrent) wantPiece(index int) bool { } func (t *torrent) connHasWantedPieces(c *connection) bool { - return c.pieceRequestOrder != nil && c.pieceRequestOrder.First() != nil + return c.pieceRequestOrder != nil && !c.pieceRequestOrder.Empty() } func (t *torrent) extentPieces(off, _len int64) (pieces []int) {