Skip to content

Commit

Permalink
core: more efficient nonce-update in txpool (#22231)
Browse files Browse the repository at this point in the history
* Adjust pending nonce update operation

Benchmark the speed of transaction insertion under multiple accounts

core: fix rebase issues + docstring

core: make benchmark test use sync:ed method

* core: address review comments

* core: add memreport to benchmark

Co-authored-by: WeiLoy <[email protected]>
  • Loading branch information
holiman and WeiLoy authored Nov 2, 2021
1 parent f49e90e commit 03bc8b7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
8 changes: 8 additions & 0 deletions core/tx_noncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,11 @@ func (txn *txNoncer) setIfLower(addr common.Address, nonce uint64) {
}
txn.nonces[addr] = nonce
}

// setAll sets the nonces for all accounts to the given map.
func (txn *txNoncer) setAll(all map[common.Address]uint64) {
txn.lock.Lock()
defer txn.lock.Unlock()

txn.nonces = all
}
12 changes: 7 additions & 5 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -1182,16 +1182,18 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt
pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead)
pool.priced.SetBaseFee(pendingBaseFee)
}
// Update all accounts to the latest known pending nonce
nonces := make(map[common.Address]uint64, len(pool.pending))
for addr, list := range pool.pending {
highestPending := list.LastElement()
nonces[addr] = highestPending.Nonce() + 1
}
pool.pendingNonces.setAll(nonces)
}
// Ensure pool.queue and pool.pending sizes stay within the configured limits.
pool.truncatePending()
pool.truncateQueue()

// Update all accounts to the latest known pending nonce
for addr, list := range pool.pending {
highestPending := list.LastElement()
pool.pendingNonces.set(addr, highestPending.Nonce()+1)
}
dropBetweenReorgHistogram.Update(int64(pool.changesSinceReorg))
pool.changesSinceReorg = 0 // Reset change counter
pool.mu.Unlock()
Expand Down
21 changes: 21 additions & 0 deletions core/tx_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2540,3 +2540,24 @@ func BenchmarkInsertRemoteWithAllLocals(b *testing.B) {
pool.Stop()
}
}

// Benchmarks the speed of batch transaction insertion in case of multiple accounts.
func BenchmarkPoolMultiAccountBatchInsert(b *testing.B) {
// Generate a batch of transactions to enqueue into the pool
pool, _ := setupTxPool()
defer pool.Stop()
b.ReportAllocs()
batches := make(types.Transactions, b.N)
for i := 0; i < b.N; i++ {
key, _ := crypto.GenerateKey()
account := crypto.PubkeyToAddress(key.PublicKey)
pool.currentState.AddBalance(account, big.NewInt(1000000))
tx := transaction(uint64(0), 100000, key)
batches[i] = tx
}
// Benchmark importing the transactions into the queue
b.ResetTimer()
for _, tx := range batches {
pool.AddRemotesSync([]*types.Transaction{tx})
}
}

0 comments on commit 03bc8b7

Please sign in to comment.