Skip to content

core/types: reduce alloc in hot code path#33523

Open
cuiweixie wants to merge 2 commits intoethereum:masterfrom
cuiweixie:cost
Open

core/types: reduce alloc in hot code path#33523
cuiweixie wants to merge 2 commits intoethereum:masterfrom
cuiweixie:cost

Conversation

@cuiweixie
Copy link
Contributor

@cuiweixie cuiweixie commented Jan 4, 2026

benchmark code:

package types

import (
	"math/big"
	"testing"

	"github.com/ethereum/go-ethereum/common"
	"github.com/holiman/uint256"
)

var benchCostSink *big.Int

// costLegacy reproduces the pre-optimization implementation of (*Transaction).Cost.
// It intentionally goes through exported accessors to include their allocations.
func costLegacy(tx *Transaction) *big.Int {
	total := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))
	if tx.Type() == BlobTxType {
		total.Add(total, new(big.Int).Mul(tx.BlobGasFeeCap(), new(big.Int).SetUint64(tx.BlobGas())))
	}
	total.Add(total, tx.Value())
	return total
}

func benchmarkCost(b *testing.B, tx *Transaction, fn func(*Transaction) *big.Int) {
	b.Helper()
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		benchCostSink = fn(tx)
	}
}

func BenchmarkTransactionCost_LegacyTx(b *testing.B) {
	to := common.HexToAddress("0x000000000000000000000000000000000000dEaD")
	tx := NewTx(&LegacyTx{
		Nonce:    1,
		Gas:      21000,
		GasPrice: big.NewInt(20_000_000_000), // 20 gwei
		To:       &to,
		Value:    big.NewInt(1_000_000_000_000_000_000), // 1 ether
		Data:     nil,
		V:        new(big.Int),
		R:        new(big.Int),
		S:        new(big.Int),
	})
	b.Helper()
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		benchCostSink = tx.Cost()
	}
}

func BenchmarkTransactionCost_BlobTx(b *testing.B) {
	to := common.HexToAddress("0x000000000000000000000000000000000000dEaD")
	tx := NewTx(&BlobTx{
		ChainID:    uint256.NewInt(1),
		Nonce:      1,
		GasTipCap:  uint256.NewInt(2_000_000_000),  // 2 gwei
		GasFeeCap:  uint256.NewInt(30_000_000_000), // 30 gwei
		Gas:        21000,
		To:         to,
		Value:      uint256.NewInt(1_000_000_000_000_000_000), // 1 ether
		Data:       nil,
		AccessList: nil,
		BlobFeeCap: uint256.NewInt(15_000_000_000), // 15 gwei per blob gas
		BlobHashes: []common.Hash{
			common.HexToHash("0x01"),
		},
		// Signature values are optional for Cost(), but set to non-nil to ensure copy() is safe.
		V: uint256.NewInt(0),
		R: uint256.NewInt(0),
		S: uint256.NewInt(0),
	})
	b.Helper()
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		benchCostSink = tx.Cost()
	}
}

result in:

goos: darwin
goarch: arm64
pkg: github.com/ethereum/go-ethereum/core/types
cpu: Apple M4 Pro
                            │   old.txt   │               new.txt               │
                            │   sec/op    │   sec/op     vs base                │
TransactionCost_LegacyTx-14   78.02n ± 3%   40.58n ± 3%  -47.98% (p=0.000 n=10)
TransactionCost_BlobTx-14     173.8n ± 2%   134.9n ± 6%  -22.41% (p=0.000 n=10)
geomean                       116.4n        73.97n       -36.47%

                            │   old.txt   │              new.txt               │
                            │    B/op     │    B/op     vs base                │
TransactionCost_LegacyTx-14   168.00 ± 0%   88.00 ± 0%  -47.62% (p=0.000 n=10)
TransactionCost_BlobTx-14      416.0 ± 0%   336.0 ± 0%  -19.23% (p=0.000 n=10)
geomean                        264.4        172.0       -34.96%

                            │  old.txt   │              new.txt               │
                            │ allocs/op  │ allocs/op   vs base                │
TransactionCost_LegacyTx-14   7.000 ± 0%   3.000 ± 0%  -57.14% (p=0.000 n=10)
TransactionCost_BlobTx-14     15.00 ± 0%   11.00 ± 0%  -26.67% (p=0.000 n=10)
geomean                       10.25        5.745       -43.94%

fjl
fjl previously approved these changes Jan 6, 2026
@fjl fjl removed the status:triage label Jan 6, 2026
Copy link
Contributor

@s1na s1na left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants