Skip to content

Commit

Permalink
Update benchmark for tx sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
2dvorak authored and yoomee1313 committed May 3, 2024
1 parent de4d9be commit e5f1892
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 3 deletions.
27 changes: 27 additions & 0 deletions blockchain/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,33 @@ func (s *TxByTime) Pop() interface{} {
return x
}

// TxByPriceAndTime implements both the sort and the heap interface, making it useful
// for all at once sorting as well as individually adding and removing elements.
type TxByPriceAndTime Transactions

func (s TxByPriceAndTime) Len() int { return len(s) }
func (s TxByPriceAndTime) Less(i, j int) bool {
// Use the time the transaction was first seen for deterministic sorting
cmp := s[i].GasPrice().Cmp(s[j].GasPrice())
if cmp == 0 {
return s[i].time.Before(s[j].time)
}
return cmp > 0
}
func (s TxByPriceAndTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }

func (s *TxByPriceAndTime) Push(x interface{}) {
*s = append(*s, x.(*Transaction))
}

func (s *TxByPriceAndTime) Pop() interface{} {
old := *s
n := len(old)
x := old[n-1]
*s = old[0 : n-1]
return x
}

// txWithMinerFee wraps a transaction with its gas price or effective miner gasTipCap
type txWithMinerFee struct {
tx *Transaction
Expand Down
77 changes: 74 additions & 3 deletions blockchain/types/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -965,16 +965,87 @@ func BenchmarkTxSortByTime20000(b *testing.B) { benchmarkTxSortByTime(b, 20000)
func benchmarkTxSortByTime(b *testing.B, size int) {
signer := LatestSignerForChainID(big.NewInt(1))

key, _ := crypto.GenerateKey()
batches := make(Transactions, size)

for i := 0; i < size; i++ {
batches[i], _ = SignTx(NewTransaction(uint64(i), common.Address{}, big.NewInt(100), 100, big.NewInt(int64(i)), nil), signer, key)
}

// Shuffle transactions.
rand.Shuffle(len(batches), func(i, j int) {
batches[i], batches[j] = batches[j], batches[i]
})

// Benchmark importing the transactions into the queue
b.ResetTimer()

for i := 0; i < b.N; i++ {
sort.Sort(TxByPriceAndTime(batches))
}
}

func BenchmarkTxSortByTimeDynamicFee30000(b *testing.B) { benchmarkTxSortByTimeDynamicFee(b, 30000) }
func BenchmarkTxSortByTimeDynamicFee20000(b *testing.B) { benchmarkTxSortByTimeDynamicFee(b, 20000) }
func benchmarkTxSortByTimeDynamicFee(b *testing.B, size int) {
signer := LatestSignerForChainID(big.NewInt(1))

key, _ := crypto.GenerateKey()
batches := make(Transactions, size)

for i := 0; i < size; i++ {
gasFeeCap := rand.Intn(50)
tx, _ := SignTx(NewTx(&TxInternalDataEthereumDynamicFee{
AccountNonce: uint64(i),
Recipient: &common.Address{},
Amount: big.NewInt(100),
GasLimit: 100,
GasFeeCap: big.NewInt(int64(gasFeeCap)),
GasTipCap: big.NewInt(int64(rand.Intn(gasFeeCap + 1))),
Payload: nil,
}), signer, key)
batches[i] = tx
}

// Should be already shuffled, but shuffle transactions anyway.
rand.Seed(time.Now().Unix())
rand.Shuffle(len(batches), func(i, j int) {
batches[i], batches[j] = batches[j], batches[i]
})

// Benchmark importing the transactions into the queue
b.ResetTimer()

for i := 0; i < b.N; i++ {
sort.Sort(TxByPriceAndTime(batches))
}
}

func BenchmarkTxSortByPrice30000(b *testing.B) { benchmarkTxSortByPrice(b, 30000) }
func BenchmarkTxSortByPrice20000(b *testing.B) { benchmarkTxSortByPrice(b, 20000) }
func benchmarkTxSortByPrice(b *testing.B, size int) {
signer := LatestSignerForChainID(big.NewInt(1))

key, _ := crypto.GenerateKey()
batches := make(txByEffectivePriceAndTime, size)

for i := 0; i < size; i++ {
tx, _ := SignTx(NewTransaction(uint64(i), common.Address{}, big.NewInt(100), 100, big.NewInt(int64(i)), nil), signer, key)
txWithFee, _ := newTxWithMinerFee(tx, common.Address{}, big.NewInt(int64(i)))
gasFeeCap := rand.Intn(50)
tx, _ := SignTx(NewTx(&TxInternalDataEthereumDynamicFee{
AccountNonce: uint64(i),
Recipient: &common.Address{},
Amount: big.NewInt(100),
GasLimit: 100,
GasFeeCap: big.NewInt(int64(gasFeeCap)),
GasTipCap: big.NewInt(int64(rand.Intn(gasFeeCap + 1))),
Payload: nil,
}), signer, key)
txWithFee, _ := newTxWithMinerFee(tx, common.Address{}, nil)
batches[i] = txWithFee
}

// Shuffle transactions.
// Should be already shuffled, but shuffle transactions anyway.
rand.Seed(time.Now().Unix())
rand.Shuffle(len(batches), func(i, j int) {
batches[i], batches[j] = batches[j], batches[i]
})
Expand Down

0 comments on commit e5f1892

Please sign in to comment.