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.MinerNoVerifyFlag,
utils.MinerStoreSkippedTxTracesFlag,
utils.MinerMaxAccountsNumFlag,
utils.NATFlag,
utils.NoDiscoverFlag,
utils.DiscoveryV5Flag,

View file

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

View file

@ -500,6 +500,11 @@ var (
Name: "miner.storeskippedtxtraces",
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
UnlockedAccountFlag = cli.StringFlag{
Name: "unlock",
@ -1519,6 +1524,9 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
if ctx.GlobalIsSet(MinerStoreSkippedTxTracesFlag.Name) {
cfg.StoreSkippedTxTraces = ctx.GlobalBool(MinerStoreSkippedTxTracesFlag.Name)
}
if ctx.GlobalIsSet(MinerMaxAccountsNumFlag.Name) {
cfg.MaxAccountsNum = ctx.GlobalInt(MinerMaxAccountsNumFlag.Name)
}
if ctx.GlobalIsSet(LegacyMinerGasTargetFlag.Name) {
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
// the next pending execution environment.
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()
defer pool.mu.Unlock()
@ -555,6 +565,9 @@ func (pool *TxPool) Pending(enforceTips bool) map[common.Address]types.Transacti
}
if len(txs) > 0 {
pending[addr] = txs
if len(pending) >= maxAccountsNum {
break
}
}
}
return pending

View file

@ -28,6 +28,8 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/core/rawdb"
"github.com/scroll-tech/go-ethereum/core/state"
@ -2575,3 +2577,27 @@ func BenchmarkPoolMultiAccountBatchInsert(b *testing.B) {
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).
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.

View file

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

View file

@ -1446,7 +1446,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
tidyPendingStart := time.Now()
// 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.
// But if we disable empty precommit already, ignore it. Since
// empty block is necessary to keep the liveness of the network.

View file

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

View file

@ -24,7 +24,7 @@ import (
const (
VersionMajor = 5 // Major 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
)