github.com/anacrolix/torrent@v1.61.0/internal/request-strategy/piece-request-order_test.go (about)

     1  package requestStrategy
     2  
     3  import (
     4  	"testing"
     5  	"unique"
     6  
     7  	"github.com/anacrolix/torrent/metainfo"
     8  	"github.com/bradfitz/iter"
     9  )
    10  
    11  func benchmarkPieceRequestOrder[B Btree](
    12  	b *testing.B,
    13  	// Initialize the next run, and return a Btree
    14  	newBtree func() B,
    15  	// Set any path hinting for the specified piece
    16  	hintForPiece func(index int),
    17  	numPieces int,
    18  ) {
    19  	b.ReportAllocs()
    20  	zeroHashHandle := unique.Make(metainfo.Hash{})
    21  	for b.Loop() {
    22  		pro := NewPieceOrder(newBtree(), numPieces)
    23  		state := PieceRequestOrderState{}
    24  		doPieces := func(m func(PieceRequestOrderKey) bool) {
    25  			for i := range iter.N(numPieces) {
    26  				key := PieceRequestOrderKey{
    27  					Index:    i,
    28  					InfoHash: zeroHashHandle,
    29  				}
    30  				hintForPiece(i)
    31  				m(key)
    32  			}
    33  		}
    34  		doPieces(func(key PieceRequestOrderKey) bool {
    35  			return !pro.Add(key, state).Ok
    36  		})
    37  		state.Availability++
    38  		doPieces(func(key PieceRequestOrderKey) bool {
    39  			pro.Update(key, state)
    40  			return true
    41  		})
    42  		pro.tree.Scan(func(item PieceRequestOrderItem) bool {
    43  			return true
    44  		})
    45  		doPieces(func(key PieceRequestOrderKey) bool {
    46  			state.Priority = piecePriority(key.Index / 4)
    47  			pro.Update(key, state)
    48  			return true
    49  		})
    50  		pro.tree.Scan(func(item PieceRequestOrderItem) bool {
    51  			return item.Key.Index < 1000
    52  		})
    53  		state.Priority = 0
    54  		state.Availability++
    55  		doPieces(func(key PieceRequestOrderKey) bool {
    56  			pro.Update(key, state)
    57  			return true
    58  		})
    59  		pro.tree.Scan(func(item PieceRequestOrderItem) bool {
    60  			return item.Key.Index < 1000
    61  		})
    62  		state.Availability--
    63  		doPieces(func(key PieceRequestOrderKey) bool {
    64  			pro.Update(key, state)
    65  			return true
    66  		})
    67  		doPieces(pro.Delete)
    68  		if pro.Len() != 0 {
    69  			b.FailNow()
    70  		}
    71  	}
    72  }
    73  
    74  func zero[T any](t *T) {
    75  	var zt T
    76  	*t = zt
    77  }
    78  
    79  func BenchmarkPieceRequestOrder(b *testing.B) {
    80  	const numPieces = 2000
    81  	b.Run("TidwallBtree", func(b *testing.B) {
    82  		b.Run("NoPathHints", func(b *testing.B) {
    83  			benchmarkPieceRequestOrder(b, NewTidwallBtree, func(int) {}, numPieces)
    84  		})
    85  		b.Run("SharedPathHint", func(b *testing.B) {
    86  			var pathHint PieceRequestOrderPathHint
    87  			var btree *tidwallBtree
    88  			benchmarkPieceRequestOrder(
    89  				b, func() *tidwallBtree {
    90  					zero(&pathHint)
    91  					btree = NewTidwallBtree()
    92  					btree.PathHint = &pathHint
    93  					return btree
    94  				}, func(int) {}, numPieces,
    95  			)
    96  		})
    97  		b.Run("PathHintPerPiece", func(b *testing.B) {
    98  			pathHints := make([]PieceRequestOrderPathHint, numPieces)
    99  			var btree *tidwallBtree
   100  			benchmarkPieceRequestOrder(
   101  				b, func() *tidwallBtree {
   102  					btree = NewTidwallBtree()
   103  					return btree
   104  				}, func(index int) {
   105  					btree.PathHint = &pathHints[index]
   106  				}, numPieces,
   107  			)
   108  		})
   109  	})
   110  	b.Run("AjwernerBtree", func(b *testing.B) {
   111  		benchmarkPieceRequestOrder(b, NewAjwernerBtree, func(index int) {}, numPieces)
   112  	})
   113  }