mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 05:36:46 +00:00
core/types: reduce allocations for transaction comparison
This commit is contained in:
parent
bf8f63dcd2
commit
c42b31a1f6
4 changed files with 63 additions and 37 deletions
|
|
@ -514,26 +514,15 @@ func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address]
|
|||
pool.mu.Lock()
|
||||
defer pool.mu.Unlock()
|
||||
|
||||
// Convert the new uint256.Int types to the old big.Int ones used by the legacy pool
|
||||
var (
|
||||
minTipBig *big.Int
|
||||
baseFeeBig *big.Int
|
||||
)
|
||||
if filter.MinTip != nil {
|
||||
minTipBig = filter.MinTip.ToBig()
|
||||
}
|
||||
if filter.BaseFee != nil {
|
||||
baseFeeBig = filter.BaseFee.ToBig()
|
||||
}
|
||||
pending := make(map[common.Address][]*txpool.LazyTransaction, len(pool.pending))
|
||||
for addr, list := range pool.pending {
|
||||
txs := list.Flatten()
|
||||
|
||||
// If the miner requests tip enforcement, cap the lists now
|
||||
if minTipBig != nil || filter.GasLimitCap != 0 {
|
||||
if filter.MinTip != nil || filter.GasLimitCap != 0 {
|
||||
for i, tx := range txs {
|
||||
if minTipBig != nil {
|
||||
if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 {
|
||||
if filter.MinTip != nil {
|
||||
if tx.EffectiveGasTipIntCmp(filter.MinTip, filter.BaseFee) < 0 {
|
||||
txs = txs[:i]
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ func (l *list) subTotalCost(txs []*types.Transaction) {
|
|||
// then the heap is sorted based on the effective tip based on the given base fee.
|
||||
// If baseFee is nil then the sorting is based on gasFeeCap.
|
||||
type priceHeap struct {
|
||||
baseFee *big.Int // heap should always be re-sorted after baseFee is changed
|
||||
baseFee *uint256.Int // heap should always be re-sorted after baseFee is changed
|
||||
list []*types.Transaction
|
||||
}
|
||||
|
||||
|
|
@ -677,6 +677,10 @@ func (l *pricedList) Reheap() {
|
|||
// SetBaseFee updates the base fee and triggers a re-heap. Note that Removed is not
|
||||
// necessary to call right before SetBaseFee when processing a new block.
|
||||
func (l *pricedList) SetBaseFee(baseFee *big.Int) {
|
||||
l.urgent.baseFee = baseFee
|
||||
base := new(uint256.Int)
|
||||
if baseFee != nil {
|
||||
base.SetFromBig(baseFee)
|
||||
}
|
||||
l.urgent.baseFee = base
|
||||
l.Reheap()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -355,51 +356,55 @@ func (tx *Transaction) GasTipCapIntCmp(other *big.Int) int {
|
|||
// Note: if the effective gasTipCap is negative, this method returns both error
|
||||
// the actual negative value, _and_ ErrGasFeeCapTooLow
|
||||
func (tx *Transaction) EffectiveGasTip(baseFee *big.Int) (*big.Int, error) {
|
||||
dst := new(big.Int)
|
||||
err := tx.calcEffectiveGasTip(dst, baseFee)
|
||||
return dst, err
|
||||
dst := new(uint256.Int)
|
||||
base := new(uint256.Int)
|
||||
if baseFee != nil {
|
||||
base.SetFromBig(baseFee)
|
||||
}
|
||||
err := tx.calcEffectiveGasTip(dst, base)
|
||||
return dst.ToBig(), err
|
||||
}
|
||||
|
||||
// calcEffectiveGasTip calculates the effective gas tip of the transaction and
|
||||
// saves the result to dst.
|
||||
func (tx *Transaction) calcEffectiveGasTip(dst *big.Int, baseFee *big.Int) error {
|
||||
func (tx *Transaction) calcEffectiveGasTip(dst *uint256.Int, baseFee *uint256.Int) error {
|
||||
if baseFee == nil {
|
||||
dst.Set(tx.inner.gasTipCap())
|
||||
dst.SetFromBig(tx.inner.gasTipCap())
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
gasFeeCap := tx.inner.gasFeeCap()
|
||||
if gasFeeCap.Cmp(baseFee) < 0 {
|
||||
dst.SetFromBig(tx.inner.gasFeeCap())
|
||||
if dst.Cmp(baseFee) < 0 {
|
||||
err = ErrGasFeeCapTooLow
|
||||
}
|
||||
|
||||
dst.Sub(gasFeeCap, baseFee)
|
||||
gasTipCap := tx.inner.gasTipCap()
|
||||
dst.Sub(dst, baseFee)
|
||||
gasTipCap := new(uint256.Int)
|
||||
gasTipCap.SetFromBig(tx.inner.gasTipCap())
|
||||
if gasTipCap.Cmp(dst) < 0 {
|
||||
dst.Set(gasTipCap)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// EffectiveGasTipCmp compares the effective gasTipCap of two transactions assuming the given base fee.
|
||||
func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *big.Int) int {
|
||||
func (tx *Transaction) EffectiveGasTipCmp(other *Transaction, baseFee *uint256.Int) int {
|
||||
if baseFee == nil {
|
||||
return tx.GasTipCapCmp(other)
|
||||
}
|
||||
// Use more efficient internal method.
|
||||
txTip, otherTip := new(big.Int), new(big.Int)
|
||||
txTip, otherTip := new(uint256.Int), new(uint256.Int)
|
||||
tx.calcEffectiveGasTip(txTip, baseFee)
|
||||
other.calcEffectiveGasTip(otherTip, baseFee)
|
||||
return txTip.Cmp(otherTip)
|
||||
}
|
||||
|
||||
// EffectiveGasTipIntCmp compares the effective gasTipCap of a transaction to the given gasTipCap.
|
||||
func (tx *Transaction) EffectiveGasTipIntCmp(other *big.Int, baseFee *big.Int) int {
|
||||
func (tx *Transaction) EffectiveGasTipIntCmp(other *uint256.Int, baseFee *uint256.Int) int {
|
||||
if baseFee == nil {
|
||||
return tx.GasTipCapIntCmp(other)
|
||||
return tx.GasTipCapIntCmp(other.ToBig())
|
||||
}
|
||||
txTip := new(big.Int)
|
||||
txTip := new(uint256.Int)
|
||||
tx.calcEffectiveGasTip(txTip, baseFee)
|
||||
return txTip.Cmp(other)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// The values in those tests are from the Transaction Tests
|
||||
|
|
@ -609,12 +610,12 @@ func BenchmarkEffectiveGasTip(b *testing.B) {
|
|||
Data: nil,
|
||||
}
|
||||
tx, _ := SignNewTx(key, signer, txdata)
|
||||
baseFee := big.NewInt(1000000000) // 1 gwei
|
||||
baseFee := uint256.NewInt(1000000000) // 1 gwei
|
||||
|
||||
b.Run("Original", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := tx.EffectiveGasTip(baseFee)
|
||||
_, err := tx.EffectiveGasTip(baseFee.ToBig())
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
|
@ -623,7 +624,7 @@ func BenchmarkEffectiveGasTip(b *testing.B) {
|
|||
|
||||
b.Run("IntoMethod", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
dst := new(big.Int)
|
||||
dst := new(uint256.Int)
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := tx.calcEffectiveGasTip(dst, baseFee)
|
||||
if err != nil {
|
||||
|
|
@ -666,23 +667,25 @@ func TestEffectiveGasTipInto(t *testing.T) {
|
|||
tx, _ := SignNewTx(key, signer, txdata)
|
||||
|
||||
var baseFee *big.Int
|
||||
var baseFee2 *uint256.Int
|
||||
if tc.baseFee != nil {
|
||||
baseFee = big.NewInt(*tc.baseFee)
|
||||
baseFee2 = uint256.NewInt(uint64(*tc.baseFee))
|
||||
}
|
||||
|
||||
// Get result from original method
|
||||
orig, origErr := tx.EffectiveGasTip(baseFee)
|
||||
|
||||
// Get result from new method
|
||||
dst := new(big.Int)
|
||||
newErr := tx.calcEffectiveGasTip(dst, baseFee)
|
||||
dst := new(uint256.Int)
|
||||
newErr := tx.calcEffectiveGasTip(dst, baseFee2)
|
||||
|
||||
// Compare results
|
||||
if (origErr != nil) != (newErr != nil) {
|
||||
t.Fatalf("case %d: error mismatch: orig %v, new %v", i, origErr, newErr)
|
||||
}
|
||||
|
||||
if orig.Cmp(dst) != 0 {
|
||||
if origErr == nil && orig.Cmp(dst.ToBig()) != 0 {
|
||||
t.Fatalf("case %d: result mismatch: orig %v, new %v", i, orig, dst)
|
||||
}
|
||||
}
|
||||
|
|
@ -692,3 +695,28 @@ func TestEffectiveGasTipInto(t *testing.T) {
|
|||
func intPtr(i int64) *int64 {
|
||||
return &i
|
||||
}
|
||||
|
||||
func BenchmarkEffectiveGasTipCmp(b *testing.B) {
|
||||
signer := LatestSigner(params.TestChainConfig)
|
||||
key, _ := crypto.GenerateKey()
|
||||
txdata := &DynamicFeeTx{
|
||||
ChainID: big.NewInt(1),
|
||||
Nonce: 0,
|
||||
GasTipCap: big.NewInt(2000000000),
|
||||
GasFeeCap: big.NewInt(3000000000),
|
||||
Gas: 21000,
|
||||
To: &common.Address{},
|
||||
Value: big.NewInt(0),
|
||||
Data: nil,
|
||||
}
|
||||
tx, _ := SignNewTx(key, signer, txdata)
|
||||
other, _ := SignNewTx(key, signer, txdata)
|
||||
baseFee := uint256.NewInt(1000000000) // 1 gwei
|
||||
|
||||
b.Run("Original", func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tx.EffectiveGasTipCmp(other, baseFee)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue