mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 19:00:46 +00:00
remove benchmarks
This commit is contained in:
parent
f0d9dc1c8b
commit
2756eedd27
11 changed files with 0 additions and 430 deletions
|
|
@ -18,12 +18,7 @@ package core
|
|||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -73,12 +68,6 @@ func BenchmarkInsertChain_ring1000_memdb(b *testing.B) {
|
|||
func BenchmarkInsertChain_ring1000_diskdb(b *testing.B) {
|
||||
benchInsertChain(b, true, genTxRing(1000))
|
||||
}
|
||||
func BenchmarkInsertChain_evmWorkload_memdb(b *testing.B) {
|
||||
benchInsertChainEVM(b, false)
|
||||
}
|
||||
func BenchmarkInsertChain_evmWorkload_diskdb(b *testing.B) {
|
||||
benchInsertChainEVM(b, true)
|
||||
}
|
||||
|
||||
var (
|
||||
// This is the content of the genesis block used by the benchmarks.
|
||||
|
|
@ -219,110 +208,6 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
|||
}
|
||||
}
|
||||
|
||||
// The evmWorkload addresses hold the evm-bench contracts (see
|
||||
// core/vm/runtime/testdata), installed through the genesis alloc. Their
|
||||
// runtime bytecode sets up all state inside Benchmark(), so no constructor
|
||||
// runs.
|
||||
var benchWorkloadAddrs = []common.Address{
|
||||
common.HexToAddress("0x00000000000000000000000000000000000e0001"), // ERC20Transfer
|
||||
common.HexToAddress("0x00000000000000000000000000000000000e0002"), // ERC20Mint
|
||||
common.HexToAddress("0x00000000000000000000000000000000000e0003"), // ERC20ApprovalTransfer
|
||||
common.HexToAddress("0x00000000000000000000000000000000000e0004"), // TenThousandHashes
|
||||
}
|
||||
|
||||
func benchWorkloadCode(tb testing.TB) [][]byte {
|
||||
files := []string{"erc20transfer.hex", "erc20mint.hex", "erc20approval.hex", "tenthousandhashes.hex"}
|
||||
codes := make([][]byte, len(files))
|
||||
for i, name := range files {
|
||||
raw, err := os.ReadFile(filepath.Join("vm", "runtime", "testdata", name))
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
}
|
||||
code, err := hex.DecodeString(strings.TrimSpace(string(raw)))
|
||||
if err != nil {
|
||||
tb.Fatal(err)
|
||||
}
|
||||
codes[i] = code
|
||||
}
|
||||
return codes
|
||||
}
|
||||
|
||||
// benchInsertChainEVM measures InsertChain over blocks dominated by real
|
||||
// contract execution, as a coarse local surrogate for sync throughput: the
|
||||
// timed path is full block processing, including sender recovery, EVM
|
||||
// execution, state updates, receipts, bloom filters and the state root.
|
||||
// Every block invokes the four evm-bench workloads (ERC-20 transfer, mint
|
||||
// and approval loops plus a keccak loop) and sends ten value transfers to
|
||||
// fresh accounts so the state grows as it would during sync. Reports Mgas/s
|
||||
// alongside the standard timings.
|
||||
func benchInsertChainEVM(b *testing.B, disk bool) {
|
||||
var db ethdb.Database
|
||||
if !disk {
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
} else {
|
||||
pdb, err := pebble.New(b.TempDir(), 128, 128, "", false)
|
||||
if err != nil {
|
||||
b.Fatalf("cannot create temporary database: %v", err)
|
||||
}
|
||||
db = rawdb.NewDatabase(pdb)
|
||||
defer db.Close()
|
||||
}
|
||||
alloc := types.GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}}
|
||||
for i, code := range benchWorkloadCode(b) {
|
||||
alloc[benchWorkloadAddrs[i]] = types.Account{Code: code, Balance: new(big.Int)}
|
||||
}
|
||||
gspec := &Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: alloc,
|
||||
GasLimit: 150_000_000,
|
||||
}
|
||||
selector := []byte{0x30, 0x62, 0x7b, 0x7c} // Benchmark()
|
||||
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), b.N, func(i int, gen *BlockGen) {
|
||||
signer := gen.Signer()
|
||||
gasPrice := big.NewInt(0)
|
||||
if gen.header.BaseFee != nil {
|
||||
gasPrice = gen.header.BaseFee
|
||||
}
|
||||
for _, addr := range benchWorkloadAddrs {
|
||||
to := addr
|
||||
tx, _ := types.SignNewTx(benchRootKey, signer, &types.LegacyTx{
|
||||
Nonce: gen.TxNonce(benchRootAddr),
|
||||
To: &to,
|
||||
Gas: 30_000_000,
|
||||
Data: selector,
|
||||
GasPrice: gasPrice,
|
||||
})
|
||||
gen.AddTx(tx)
|
||||
}
|
||||
for j := 0; j < 10; j++ {
|
||||
var to common.Address
|
||||
binary.BigEndian.PutUint64(to[4:12], uint64(i+1))
|
||||
binary.BigEndian.PutUint64(to[12:20], uint64(j+1))
|
||||
tx, _ := types.SignNewTx(benchRootKey, signer, &types.LegacyTx{
|
||||
Nonce: gen.TxNonce(benchRootAddr),
|
||||
To: &to,
|
||||
Value: big.NewInt(1),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: gasPrice,
|
||||
})
|
||||
gen.AddTx(tx)
|
||||
}
|
||||
})
|
||||
var totalGas uint64
|
||||
for _, block := range chain {
|
||||
totalGas += block.GasUsed()
|
||||
}
|
||||
chainman, _ := NewBlockChain(db, gspec, ethash.NewFaker(), nil)
|
||||
defer chainman.Stop()
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
if i, err := chainman.InsertChain(chain); err != nil {
|
||||
b.Fatalf("insert error (block %d): %v\n", i, err)
|
||||
}
|
||||
b.StopTimer()
|
||||
b.ReportMetric(float64(totalGas)/1e6/b.Elapsed().Seconds(), "Mgas/s")
|
||||
}
|
||||
|
||||
func BenchmarkChainRead_header_10k(b *testing.B) {
|
||||
benchReadChain(b, false, 10000)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,106 +0,0 @@
|
|||
// Copyright 2026 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Whole-contract interpreter benchmarks from the evm-bench suite
|
||||
// (github.com/ziyadedher/evm-bench). Each contract exposes a Benchmark()
|
||||
// entrypoint (selector 0x30627b7c) that performs the whole workload internally
|
||||
// (e.g. 5000 mints), so the benchmark is a single Call per iteration. These
|
||||
// complement the opcode/loop micro-benchmarks in runtime_test.go with realistic
|
||||
// workloads (a ray tracer, ERC-20 transfer/mint/approval, a hashing loop) and
|
||||
// use the same names as evm-bench / gevm for cross-comparison.
|
||||
//
|
||||
// Run: go test ./core/vm/runtime/ -run '^$' -bench 'Benchmark(Snailtracer|TenThousandHashes|ERC20)' -benchmem -count=10
|
||||
// Compare A/B: ./core/vm/runtime/testdata/evm-bench/compare.sh
|
||||
//
|
||||
// The committed runtime bytecode in testdata/*.hex is regenerated by
|
||||
// testdata/evm-bench/gen.sh (solc via docker). See that script for provenance
|
||||
// and exact compiler versions.
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
//go:embed testdata/snailtracer.hex
|
||||
var benchSnailtracerHex string
|
||||
|
||||
//go:embed testdata/tenthousandhashes.hex
|
||||
var benchTenThousandHashesHex string
|
||||
|
||||
//go:embed testdata/erc20transfer.hex
|
||||
var benchERC20TransferHex string
|
||||
|
||||
//go:embed testdata/erc20mint.hex
|
||||
var benchERC20MintHex string
|
||||
|
||||
//go:embed testdata/erc20approval.hex
|
||||
var benchERC20ApprovalHex string
|
||||
|
||||
// benchmarkSelector is keccak256("Benchmark()")[:4], the evm-bench entrypoint.
|
||||
var benchmarkSelector = []byte{0x30, 0x62, 0x7b, 0x7c}
|
||||
|
||||
func benchHexToBytes(s string) []byte {
|
||||
b, err := hex.DecodeString(strings.TrimSpace(s))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// runEVMBench deploys the contract's runtime bytecode and repeatedly invokes its
|
||||
// Benchmark() entrypoint. The contract's constructor is not run, so storage
|
||||
// starts empty. The evm-bench contracts set up whatever state they need inside
|
||||
// Benchmark(), which matches the work the evm-bench harness measures.
|
||||
func runEVMBench(b *testing.B, codeHex string) {
|
||||
code := benchHexToBytes(codeHex)
|
||||
statedb, err := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
contract := common.BytesToAddress([]byte{0x10})
|
||||
caller := common.BytesToAddress([]byte{0x01})
|
||||
statedb.CreateAccount(caller)
|
||||
statedb.AddBalance(caller, uint256.NewInt(1_000_000_000), tracing.BalanceChangeUnspecified)
|
||||
statedb.SetCode(contract, code, tracing.CodeChangeUnspecified)
|
||||
|
||||
cfg := &Config{Origin: caller, State: statedb, GasLimit: 10_000_000_000}
|
||||
|
||||
// Sanity: the workload must run to completion, not revert/out-of-gas.
|
||||
if _, _, err := Call(contract, benchmarkSelector, cfg); err != nil {
|
||||
b.Fatalf("Benchmark() did not complete: %v", err)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
Call(contract, benchmarkSelector, cfg)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSnailtracer(b *testing.B) { runEVMBench(b, benchSnailtracerHex) }
|
||||
func BenchmarkTenThousandHashes(b *testing.B) { runEVMBench(b, benchTenThousandHashesHex) }
|
||||
func BenchmarkERC20Transfer(b *testing.B) { runEVMBench(b, benchERC20TransferHex) }
|
||||
func BenchmarkERC20Mint(b *testing.B) { runEVMBench(b, benchERC20MintHex) }
|
||||
func BenchmarkERC20ApprovalTransfer(b *testing.B) { runEVMBench(b, benchERC20ApprovalHex) }
|
||||
1
core/vm/runtime/testdata/erc20approval.hex
vendored
1
core/vm/runtime/testdata/erc20approval.hex
vendored
File diff suppressed because one or more lines are too long
1
core/vm/runtime/testdata/erc20mint.hex
vendored
1
core/vm/runtime/testdata/erc20mint.hex
vendored
|
|
@ -1 +0,0 @@
|
|||
608060405234801561001057600080fd5b50600436106100b45760003560e01c80633950935111610071578063395093511461013857806370a082311461014b57806395d89b4114610174578063a457c2d71461017c578063a9059cbb1461018f578063dd62ed3e146101a257600080fd5b806306fdde03146100b9578063095ea7b3146100d757806318160ddd146100fa57806323b872dd1461010c57806330627b7c1461011f578063313ce56714610129575b600080fd5b6100c16101b5565b6040516100ce919061079c565b60405180910390f35b6100ea6100e5366004610806565b610247565b60405190151581526020016100ce565b6002545b6040519081526020016100ce565b6100ea61011a366004610830565b610261565b610127610285565b005b604051601281526020016100ce565b6100ea610146366004610806565b6102b1565b6100fe61015936600461086c565b6001600160a01b031660009081526020819052604090205490565b6100c16102d3565b6100ea61018a366004610806565b6102e2565b6100ea61019d366004610806565b610362565b6100fe6101b036600461088e565b610370565b6060600380546101c4906108c1565b80601f01602080910402602001604051908101604052809291908181526020018280546101f0906108c1565b801561023d5780601f106102125761010080835404028352916020019161023d565b820191906000526020600020905b81548152906001019060200180831161022057829003601f168201915b5050505050905090565b60003361025581858561039b565b60019150505b92915050565b60003361026f8582856104bf565b61027a858585610539565b506001949350505050565b60005b6113888110156102ae5761029c33826106dd565b806102a681610911565b915050610288565b50565b6000336102558185856102c48383610370565b6102ce919061092a565b61039b565b6060600480546101c4906108c1565b600033816102f08286610370565b9050838110156103555760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b61027a828686840361039b565b600033610255818585610539565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6001600160a01b0383166103fd5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161034c565b6001600160a01b03821661045e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161034c565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006104cb8484610370565b9050600019811461053357818110156105265760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161034c565b610533848484840361039b565b50505050565b6001600160a01b03831661059d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161034c565b6001600160a01b0382166105ff5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161034c565b6001600160a01b038316600090815260208190526040902054818110156106775760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b606482015260840161034c565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610533565b6001600160a01b0382166107335760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161034c565b8060026000828254610745919061092a565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b600060208083528351808285015260005b818110156107c9578581018301518582016040015282016107ad565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461080157600080fd5b919050565b6000806040838503121561081957600080fd5b610822836107ea565b946020939093013593505050565b60008060006060848603121561084557600080fd5b61084e846107ea565b925061085c602085016107ea565b9150604084013590509250925092565b60006020828403121561087e57600080fd5b610887826107ea565b9392505050565b600080604083850312156108a157600080fd5b6108aa836107ea565b91506108b8602084016107ea565b90509250929050565b600181811c908216806108d557607f821691505b6020821081036108f557634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600060018201610923576109236108fb565b5060010190565b8082018082111561025b5761025b6108fb56fea2646970667358221220fa5dc8b94ca8266a9f37b573a3ac8993380ce8da74caa7732abd6e7ed31cd37e64736f6c63430008110033
|
||||
1
core/vm/runtime/testdata/erc20transfer.hex
vendored
1
core/vm/runtime/testdata/erc20transfer.hex
vendored
File diff suppressed because one or more lines are too long
73
core/vm/runtime/testdata/evm-bench/README.md
vendored
73
core/vm/runtime/testdata/evm-bench/README.md
vendored
|
|
@ -1,73 +0,0 @@
|
|||
# evm-bench whole-contract interpreter benchmarks
|
||||
|
||||
Realistic-workload benchmarks for the `core/vm` interpreter, driven by contracts
|
||||
from the [evm-bench](https://github.com/ziyadedher/evm-bench) suite. They
|
||||
complement the opcode/loop micro-benchmarks in `runtime_test.go`.
|
||||
|
||||
- Benchmark code: [`core/vm/runtime/evm_bench_test.go`](../../evm_bench_test.go)
|
||||
- Runtime bytecode: `core/vm/runtime/testdata/*.hex` (committed, `//go:embed`-ed)
|
||||
|
||||
Each contract exposes a `Benchmark()` entrypoint (selector `0x30627b7c`) that
|
||||
performs the entire workload internally, so one `runtime.Call` = one full
|
||||
workload:
|
||||
|
||||
| benchmark | workload |
|
||||
|---|---|
|
||||
| `Snailtracer` | a ray tracer, compute and memory heavy |
|
||||
| `ERC20Transfer` | ERC-20 transfers in a loop |
|
||||
| `ERC20Mint` | 5000 `_mint`s (SSTORE/keccak/LOG-heavy) |
|
||||
| `ERC20ApprovalTransfer` | 1000 approve+transferFrom cycles |
|
||||
| `TenThousandHashes` | 20000 chained keccak256 calls |
|
||||
|
||||
## Running
|
||||
|
||||
```sh
|
||||
# all of them, current build
|
||||
go test ./core/vm/runtime/ -run '^$' -bench 'Benchmark(Snailtracer|TenThousandHashes|ERC20)' -benchmem -count=10
|
||||
|
||||
# A/B vs a baseline (default master), with benchstat
|
||||
core/vm/runtime/testdata/evm-bench/compare.sh # vs master
|
||||
core/vm/runtime/testdata/evm-bench/compare.sh HEAD~1 8 # vs another ref, count=8
|
||||
```
|
||||
|
||||
`compare.sh` benches the current working tree and a baseline ref (checked out in
|
||||
a throwaway worktree with this suite copied in, so it works whether or not the
|
||||
interpreter change is committed) and runs `benchstat`. Besides the contract
|
||||
workloads it runs both `BenchmarkInsertChain_evmWorkload` variants from
|
||||
`core/bench_test.go`, which push blocks carrying these contracts through the
|
||||
full block import path (state in memory and on disk) and report Mgas/s, as a
|
||||
local stand-in for sync throughput. The synthetic dispatch loops (`BenchmarkSimpleLoop/loop*` in
|
||||
`core/vm/runtime/runtime_test.go`) are not part of the A/B suite, but can
|
||||
still be run manually to isolate dispatch overhead.
|
||||
|
||||
## Regenerating the bytecode
|
||||
|
||||
[`gen.sh`](gen.sh) regenerates the ERC-20 and ten-thousand-hashes `.hex` from
|
||||
the evm-bench Solidity sources (solc 0.8.17 via docker). These contracts set up
|
||||
their state inside `Benchmark()`, so the runtime bytecode is callable directly.
|
||||
|
||||
`TenThousandHashes` is compiled from the vendored
|
||||
[`TenThousandHashes.sol`](TenThousandHashes.sol) in this directory, not the
|
||||
upstream evm-bench file. Upstream discards the hash result, so solc's optimizer
|
||||
deletes the keccak256 and the compiled benchmark degenerates into a bare
|
||||
counter loop performing a single static hash. The vendored copy chains the hash
|
||||
through a returned accumulator so the optimized bytecode performs all 20000
|
||||
hashes. Numbers for this benchmark are therefore not comparable with evm-bench
|
||||
or gevm published tables, which use degenerate bytecode (gevm's local
|
||||
replacement is broken differently, an inverted loop bound that hashes once).
|
||||
|
||||
`snailtracer.hex` is **vendored, not regenerated by gen.sh**: evm-bench's
|
||||
`SnailTracer` initializes its scene in the constructor, so its runtime bytecode
|
||||
(no constructor) renders an empty scene. The committed file is a runtime-callable
|
||||
build (scene encoded in code) vendored from
|
||||
[Giulio2002/gevm](https://github.com/Giulio2002/gevm)'s gethbench testdata.
|
||||
|
||||
The `.hex` files are committed, so running the benchmarks needs no toolchain.
|
||||
|
||||
## Notes
|
||||
|
||||
- The contract constructor is not executed, so storage starts empty. The
|
||||
evm-bench contracts set up whatever state they need inside `Benchmark()`,
|
||||
matching the work the evm-bench harness measures.
|
||||
- Names match evm-bench / gevm for cross-comparison, except `TenThousandHashes`
|
||||
(see the regenerating section).
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0
|
||||
pragma solidity ^0.8.17;
|
||||
|
||||
// Vendored from evm-bench (github.com/ziyadedher/evm-bench) with one fix.
|
||||
// The upstream loop discards the keccak256 result, so solc's optimizer
|
||||
// removes the pure call entirely and the compiled benchmark degenerates
|
||||
// into a bare counter loop that performs a single static hash. Chaining
|
||||
// the hash through an accumulator that the function returns keeps all
|
||||
// 20000 hashes in the optimized bytecode. The Benchmark() selector is
|
||||
// unchanged because return types are not part of the signature.
|
||||
contract TenThousandHashes {
|
||||
function Benchmark() external pure returns (bytes32 acc) {
|
||||
for (uint256 i = 0; i < 20000; i++) {
|
||||
acc = keccak256(abi.encodePacked(acc, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
62
core/vm/runtime/testdata/evm-bench/compare.sh
vendored
62
core/vm/runtime/testdata/evm-bench/compare.sh
vendored
|
|
@ -1,62 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# A/B benchmark of the codegen interpreter vs a baseline: runs the evm-bench
|
||||
# contract workloads (core/vm/runtime/evm_bench_test.go) plus the block import
|
||||
# benchmark (core/bench_test.go, BenchmarkInsertChain_evmWorkload, a local
|
||||
# stand-in for sync throughput) on the current working tree and on a baseline
|
||||
# ref, then benchstats them.
|
||||
#
|
||||
# The baseline is checked out in a throwaway git worktree and this suite is
|
||||
# copied into it, so the comparison works whether or not the interpreter changes
|
||||
# are committed yet. Requires: go, git, and benchstat
|
||||
# (go install golang.org/x/perf/cmd/benchstat@latest).
|
||||
#
|
||||
# Usage: core/vm/runtime/testdata/evm-bench/compare.sh [baseref] [count]
|
||||
# baseref defaults to "master", count to 10.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/../../../../.." && pwd)" # repo root
|
||||
cd "$ROOT"
|
||||
BASEREF="${1:-master}"
|
||||
COUNT="${2:-10}"
|
||||
# Each benchmark runs a FIXED iteration count instead of the default 1s of
|
||||
# benchtime. With time-based benchtime the faster side runs more iterations,
|
||||
# so one-time costs (map growth, pool warmup) amortize over a different N and
|
||||
# B/op picks up phantom deltas, and GC pacing can do the same to sec/op. Fixed
|
||||
# N makes both sides do identical work. The counts target roughly one second
|
||||
# per count on a fast box. Each entry is package:pattern:iterations.
|
||||
BENCHES=(
|
||||
'./core/vm/runtime/:^BenchmarkSnailtracer$:20x'
|
||||
'./core/vm/runtime/:^BenchmarkTenThousandHashes$:100x'
|
||||
'./core/vm/runtime/:^BenchmarkERC20Transfer$:100x'
|
||||
'./core/vm/runtime/:^BenchmarkERC20Mint$:150x'
|
||||
'./core/vm/runtime/:^BenchmarkERC20ApprovalTransfer$:120x'
|
||||
'./core/:^BenchmarkInsertChain_evmWorkload_memdb$:10x'
|
||||
'./core/:^BenchmarkInsertChain_evmWorkload_diskdb$:10x'
|
||||
)
|
||||
NEW="$(mktemp)"; OLD="$(mktemp)"
|
||||
|
||||
run_suite() { # run_suite <dir> <outfile>
|
||||
local dir="$1" out="$2" entry pkg pat n
|
||||
for entry in "${BENCHES[@]}"; do
|
||||
pkg="${entry%%:*}"
|
||||
pat="${entry#*:}"; pat="${pat%:*}"
|
||||
n="${entry##*:}"
|
||||
( cd "$dir" && go test "$pkg" -run '^$' -bench "$pat" -benchmem -benchtime "$n" -count="$COUNT" ) | tee -a "$out"
|
||||
done
|
||||
}
|
||||
|
||||
echo "==> current working tree"
|
||||
run_suite "$ROOT" "$NEW"
|
||||
|
||||
echo "==> baseline: $BASEREF (throwaway worktree, suite copied in)"
|
||||
WT="$(mktemp -d)"
|
||||
git worktree add --quiet --detach "$WT" "$BASEREF"
|
||||
cp core/vm/runtime/evm_bench_test.go "$WT/core/vm/runtime/"
|
||||
cp core/bench_test.go "$WT/core/bench_test.go"
|
||||
mkdir -p "$WT/core/vm/runtime/testdata"
|
||||
cp core/vm/runtime/testdata/*.hex "$WT/core/vm/runtime/testdata/"
|
||||
run_suite "$WT" "$OLD"
|
||||
git worktree remove --force "$WT"
|
||||
|
||||
echo "==> benchstat: $BASEREF (left) vs working tree (right)"
|
||||
benchstat "$OLD" "$NEW"
|
||||
52
core/vm/runtime/testdata/evm-bench/gen.sh
vendored
52
core/vm/runtime/testdata/evm-bench/gen.sh
vendored
|
|
@ -1,52 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# Regenerates core/vm/runtime/testdata/*.hex, the runtime bytecode for the
|
||||
# whole-contract interpreter benchmarks (see core/vm/runtime/evm_bench_test.go).
|
||||
#
|
||||
# Source: the evm-bench suite (github.com/ziyadedher/evm-bench). Each contract
|
||||
# exposes Benchmark() (selector 0x30627b7c) which performs the whole workload.
|
||||
# Compiled with solc via docker (no local solc needed). solc versions match each
|
||||
# contract's pragma: 0.8.17 for the ERC-20/hashing contracts, 0.4.26 for the
|
||||
# legacy SnailTracer.
|
||||
#
|
||||
# TenThousandHashes is compiled from the vendored TenThousandHashes.sol in
|
||||
# this directory rather than the upstream file. Upstream discards the hash
|
||||
# result, so the optimizer deletes the keccak256 and the benchmark degenerates
|
||||
# into a bare counter loop. The vendored copy chains the hash through a
|
||||
# returned accumulator, which keeps all 20000 hashes in the bytecode. See the
|
||||
# comment in that file.
|
||||
#
|
||||
# Usage: core/vm/runtime/testdata/evm-bench/gen.sh
|
||||
set -euo pipefail
|
||||
|
||||
TD="$(cd "$(dirname "$0")/.." && pwd)" # .../core/vm/runtime/testdata
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)" # .../testdata/evm-bench
|
||||
WORK="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORK"' EXIT
|
||||
|
||||
git clone --depth 1 https://github.com/ziyadedher/evm-bench "$WORK/evm-bench" >/dev/null 2>&1
|
||||
B="$WORK/evm-bench/benchmarks"
|
||||
cp "$HERE/TenThousandHashes.sol" "$B/ten-thousand-hashes/TenThousandHashes.sol"
|
||||
|
||||
# ERC-20 (transfer/mint/approval) + ten-thousand-hashes: pragma ^0.8.17. These
|
||||
# set up all their state inside Benchmark(), so the runtime bytecode is callable
|
||||
# directly with no constructor, which is how the benchmark drives them.
|
||||
docker run --rm -v "$B":/src -w /src ethereum/solc:0.8.17 \
|
||||
--optimize --bin-runtime --overwrite -o /src/out \
|
||||
erc20/transfer/ERC20Transfer.sol \
|
||||
erc20/mint/ERC20Mint.sol \
|
||||
erc20/approval-transfer/ERC20ApprovalTransfer.sol \
|
||||
ten-thousand-hashes/TenThousandHashes.sol
|
||||
|
||||
cp "$B/out/TenThousandHashes.bin-runtime" "$TD/tenthousandhashes.hex"
|
||||
cp "$B/out/ERC20Transfer.bin-runtime" "$TD/erc20transfer.hex"
|
||||
cp "$B/out/ERC20Mint.bin-runtime" "$TD/erc20mint.hex"
|
||||
cp "$B/out/ERC20ApprovalTransfer.bin-runtime" "$TD/erc20approval.hex"
|
||||
|
||||
# NOTE: snailtracer.hex is not regenerated here. evm-bench's SnailTracer
|
||||
# initializes its scene in the constructor, so its --bin-runtime (no constructor)
|
||||
# renders an empty scene. The committed snailtracer.hex is a runtime-callable
|
||||
# build (scene encoded in code, Benchmark() self-contained) vendored from
|
||||
# Giulio2002/gevm's gethbench testdata. Leave it as-is.
|
||||
|
||||
echo "regenerated (snailtracer.hex left vendored):"
|
||||
ls -l "$TD"/*.hex
|
||||
1
core/vm/runtime/testdata/snailtracer.hex
vendored
1
core/vm/runtime/testdata/snailtracer.hex
vendored
File diff suppressed because one or more lines are too long
|
|
@ -1 +0,0 @@
|
|||
6080604052348015600f57600080fd5b506004361060285760003560e01c806330627b7c14602d575b600080fd5b60336045565b60405190815260200160405180910390f35b6000805b614e20811015608e57604080516020810184905290810182905260600160405160208183030381529060405280519060200120915080806087906092565b9150506049565b5090565b60006001820160b157634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212207f65e4c71aef311b81ff8b065cdd78f5be33f5dc80d3b2318e118075e33697f164736f6c63430008110033
|
||||
Loading…
Reference in a new issue