From 013ce93396e4e8d13de8be791067bfccc04b6284 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Sat, 11 Dec 2021 23:20:47 -0800 Subject: [PATCH] x/evm/keeper: save 24B with Go in-condition variable idiom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The prior code doubly invoked (*ethereum/go-ethereum/core/types.Transaction).To() which is quite expensive, and firstly copies 20 bytes each time, then that gets rounded up to the proper size class/pointer alignment so on 64-bit machines 20B -> 24B. Isolating a benchmark for this code per issue #826 shows this saves quite a bit of bytes and some nano seconds which all count up towards the transactions per seconds being processed: ```shell $ benchstat before.txt after.txt name old time/op new time/op delta CopyAddr-8 38.4ns ± 3% 19.3ns ± 3% -49.66% (p=0.000 n=10+10) name old alloc/op new alloc/op delta CopyAddr-8 48.0B ± 0% 24.0B ± 0% -50.00% (p=0.000 n=10+10) name old allocs/op new allocs/op delta CopyAddr-8 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10) ``` Fixes #826 --- x/evm/keeper/benchmark_test.go | 33 +++++++++++++++++++++++++++++++++ x/evm/keeper/msg_server.go | 4 ++-- x/evm/keeper/statedb.go | 5 ++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/x/evm/keeper/benchmark_test.go b/x/evm/keeper/benchmark_test.go index c312681508..69ad2639b8 100644 --- a/x/evm/keeper/benchmark_test.go +++ b/x/evm/keeper/benchmark_test.go @@ -180,3 +180,36 @@ func BenchmarkDeepContextStack10(b *testing.B) { func BenchmarkDeepContextStack13(b *testing.B) { DoBenchmarkDeepContextStack(b, 13) } + +func before() *big.Int { + b2 := new(big.Int).SetUint64(2) + return new(big.Int).Mul(b2, new(big.Int).SetUint64(34)) +} + +func after() *big.Int { + b2 := new(big.Int).SetUint64(2) + return b2 + return b2.Mul(b2, new(big.Int).SetUint64(34)) +} + +var sink interface{} + +func BenchmarkMulBefore(b *testing.B) { + for i := 0; i < b.N; i++ { + sink = before() + } + if sink == nil { + b.Fatal("Benchmark did not run") + } + sink = (interface{})(nil) +} + +func BenchmarkMulAfter(b *testing.B) { + for i := 0; i < b.N; i++ { + sink = after() + } + if sink == nil { + b.Fatal("Benchmark did not run") + } + sink = (interface{})(nil) +} diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index c12a877c84..df132a4f05 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -44,8 +44,8 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyTxHash, hash.String())) } - if tx.To() != nil { - attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyRecipient, tx.To().Hex())) + if to := tx.To(); to != nil { + attrs = append(attrs, sdk.NewAttribute(types.AttributeKeyRecipient, to.Hex())) } if response.Failed() { diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index ac1cef6650..4a912ede9e 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -623,12 +623,15 @@ func (k *Keeper) Empty(addr common.Address) bool { codeHash = common.HexToHash(ethAccount.CodeHash).Bytes() } + if nonce == 0 { + return false + } balance := k.GetBalance(addr) hasZeroBalance := balance.Sign() == 0 hasEmptyCodeHash := bytes.Equal(codeHash, types.EmptyCodeHash) - return hasZeroBalance && nonce == 0 && hasEmptyCodeHash + return hasZeroBalance && hasEmptyCodeHash } // ----------------------------------------------------------------------------