feat(worker): try to limit the number of txns miner has to deal with (#745)

to reduce the effect of having a huge backlog on performance
This commit is contained in:
Ömer Faruk Irmak 2024-05-13 09:20:55 +03:00 committed by GitHub
parent abca104d18
commit 12871c7745
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 59 additions and 5 deletions

View file

@ -131,6 +131,7 @@ var (
utils.MinerRecommitIntervalFlag, utils.MinerRecommitIntervalFlag,
utils.MinerNoVerifyFlag, utils.MinerNoVerifyFlag,
utils.MinerStoreSkippedTxTracesFlag, utils.MinerStoreSkippedTxTracesFlag,
utils.MinerMaxAccountsNumFlag,
utils.NATFlag, utils.NATFlag,
utils.NoDiscoverFlag, utils.NoDiscoverFlag,
utils.DiscoveryV5Flag, utils.DiscoveryV5Flag,

View file

@ -194,6 +194,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.MinerRecommitIntervalFlag, utils.MinerRecommitIntervalFlag,
utils.MinerNoVerifyFlag, utils.MinerNoVerifyFlag,
utils.MinerStoreSkippedTxTracesFlag, utils.MinerStoreSkippedTxTracesFlag,
utils.MinerMaxAccountsNumFlag,
}, },
}, },
{ {

View file

@ -500,6 +500,11 @@ var (
Name: "miner.storeskippedtxtraces", Name: "miner.storeskippedtxtraces",
Usage: "Store the wrapped traces when storing a skipped tx", Usage: "Store the wrapped traces when storing a skipped tx",
} }
MinerMaxAccountsNumFlag = cli.IntFlag{
Name: "miner.maxaccountsnum",
Usage: "Maximum number of accounts that miner will fetch the pending transactions of when building a new block",
Value: math.MaxInt,
}
// Account settings // Account settings
UnlockedAccountFlag = cli.StringFlag{ UnlockedAccountFlag = cli.StringFlag{
Name: "unlock", Name: "unlock",
@ -1519,6 +1524,9 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
if ctx.GlobalIsSet(MinerStoreSkippedTxTracesFlag.Name) { if ctx.GlobalIsSet(MinerStoreSkippedTxTracesFlag.Name) {
cfg.StoreSkippedTxTraces = ctx.GlobalBool(MinerStoreSkippedTxTracesFlag.Name) cfg.StoreSkippedTxTraces = ctx.GlobalBool(MinerStoreSkippedTxTracesFlag.Name)
} }
if ctx.GlobalIsSet(MinerMaxAccountsNumFlag.Name) {
cfg.MaxAccountsNum = ctx.GlobalInt(MinerMaxAccountsNumFlag.Name)
}
if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) { if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) {
log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!") log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!")
} }

View file

@ -537,6 +537,16 @@ func (pool *TxPool) ContentFrom(addr common.Address) (types.Transactions, types.
// transactions and only return those whose **effective** tip is large enough in // transactions and only return those whose **effective** tip is large enough in
// the next pending execution environment. // the next pending execution environment.
func (pool *TxPool) Pending(enforceTips bool) map[common.Address]types.Transactions { func (pool *TxPool) Pending(enforceTips bool) map[common.Address]types.Transactions {
return pool.pendingWithMax(enforceTips, math.MaxInt)
}
// PendingWithMax works similar to Pending but allows setting an upper limit on how many
// accounts to return
func (pool *TxPool) PendingWithMax(enforceTips bool, maxAccountsNum int) map[common.Address]types.Transactions {
return pool.pendingWithMax(enforceTips, maxAccountsNum)
}
func (pool *TxPool) pendingWithMax(enforceTips bool, maxAccountsNum int) map[common.Address]types.Transactions {
pool.mu.Lock() pool.mu.Lock()
defer pool.mu.Unlock() defer pool.mu.Unlock()
@ -555,6 +565,9 @@ func (pool *TxPool) Pending(enforceTips bool) map[common.Address]types.Transacti
} }
if len(txs) > 0 { if len(txs) > 0 {
pending[addr] = txs pending[addr] = txs
if len(pending) >= maxAccountsNum {
break
}
} }
} }
return pending return pending

View file

@ -28,6 +28,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert"
"github.com/scroll-tech/go-ethereum/common" "github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state" "github.com/scroll-tech/go-ethereum/core/state"
@ -2575,3 +2577,27 @@ func BenchmarkPoolMultiAccountBatchInsert(b *testing.B) {
pool.AddRemotesSync([]*types.Transaction{tx}) pool.AddRemotesSync([]*types.Transaction{tx})
} }
} }
func TestPoolPending(t *testing.T) {
// Generate a batch of transactions to enqueue into the pool
pool, _ := setupTxPool()
defer pool.Stop()
numTxns := 100
batches := make(types.Transactions, numTxns)
for i := 0; i < numTxns; 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
for _, tx := range batches {
pool.AddRemotesSync([]*types.Transaction{tx})
}
assert.Len(t, pool.Pending(false), numTxns)
maxAccounts := 10
assert.Len(t, pool.PendingWithMax(false, maxAccounts), maxAccounts)
}

View file

@ -58,6 +58,7 @@ type Config struct {
Noverify bool // Disable remote mining solution verification(only useful in ethash). Noverify bool // Disable remote mining solution verification(only useful in ethash).
StoreSkippedTxTraces bool // Whether store the wrapped traces when storing a skipped tx StoreSkippedTxTraces bool // Whether store the wrapped traces when storing a skipped tx
MaxAccountsNum int // Maximum number of accounts that miner will fetch the pending transactions of when building a new block
} }
// Miner creates blocks and searches for proof-of-work values. // Miner creates blocks and searches for proof-of-work values.

View file

@ -18,6 +18,7 @@
package miner package miner
import ( import (
"math"
"testing" "testing"
"time" "time"
@ -244,7 +245,8 @@ func waitForMiningState(t *testing.T, m *Miner, mining bool) {
func createMiner(t *testing.T) (*Miner, *event.TypeMux) { func createMiner(t *testing.T) (*Miner, *event.TypeMux) {
// Create Ethash config // Create Ethash config
config := Config{ config := Config{
Etherbase: common.HexToAddress("123456789"), Etherbase: common.HexToAddress("123456789"),
MaxAccountsNum: math.MaxInt,
} }
// Create chainConfig // Create chainConfig
memdb := memorydb.New() memdb := memorydb.New()

View file

@ -1446,7 +1446,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
tidyPendingStart := time.Now() tidyPendingStart := time.Now()
// Fill the block with all available pending transactions. // Fill the block with all available pending transactions.
pending := w.eth.TxPool().Pending(false) pending := w.eth.TxPool().PendingWithMax(false, w.config.MaxAccountsNum)
// Short circuit if there is no available pending transactions. // Short circuit if there is no available pending transactions.
// But if we disable empty precommit already, ignore it. Since // But if we disable empty precommit already, ignore it. Since
// empty block is necessary to keep the liveness of the network. // empty block is necessary to keep the liveness of the network.

View file

@ -17,6 +17,7 @@
package miner package miner
import ( import (
"math"
"math/big" "math/big"
"math/rand" "math/rand"
"sync/atomic" "sync/atomic"
@ -70,8 +71,9 @@ var (
newTxs []*types.Transaction newTxs []*types.Transaction
testConfig = &Config{ testConfig = &Config{
Recommit: time.Second, Recommit: time.Second,
GasCeil: params.GenesisGasLimit, GasCeil: params.GenesisGasLimit,
MaxAccountsNum: math.MaxInt,
} }
) )

View file

@ -24,7 +24,7 @@ import (
const ( const (
VersionMajor = 5 // Major version component of the current release VersionMajor = 5 // Major version component of the current release
VersionMinor = 3 // Minor version component of the current release VersionMinor = 3 // Minor version component of the current release
VersionPatch = 14 // Patch version component of the current release VersionPatch = 15 // Patch version component of the current release
VersionMeta = "mainnet" // Version metadata to append to the version string VersionMeta = "mainnet" // Version metadata to append to the version string
) )