github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/bench_test.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "crypto/ecdsa" 21 "io/ioutil" 22 "math/big" 23 "os" 24 "testing" 25 26 "github.com/ethereumproject/go-ethereum/common" 27 "github.com/ethereumproject/go-ethereum/core/types" 28 "github.com/ethereumproject/go-ethereum/crypto" 29 "github.com/ethereumproject/go-ethereum/ethdb" 30 "github.com/ethereumproject/go-ethereum/event" 31 ) 32 33 func BenchmarkInsertChain_empty_memdb(b *testing.B) { 34 benchInsertChain(b, false, nil) 35 } 36 func BenchmarkInsertChain_empty_diskdb(b *testing.B) { 37 benchInsertChain(b, true, nil) 38 } 39 func BenchmarkInsertChain_valueTx_memdb(b *testing.B) { 40 benchInsertChain(b, false, genValueTx(0)) 41 } 42 func BenchmarkInsertChain_valueTx_diskdb(b *testing.B) { 43 benchInsertChain(b, true, genValueTx(0)) 44 } 45 func BenchmarkInsertChain_valueTx_100kB_memdb(b *testing.B) { 46 benchInsertChain(b, false, genValueTx(100*1024)) 47 } 48 func BenchmarkInsertChain_valueTx_100kB_diskdb(b *testing.B) { 49 benchInsertChain(b, true, genValueTx(100*1024)) 50 } 51 func BenchmarkInsertChain_uncles_memdb(b *testing.B) { 52 benchInsertChain(b, false, genUncles) 53 } 54 func BenchmarkInsertChain_uncles_diskdb(b *testing.B) { 55 benchInsertChain(b, true, genUncles) 56 } 57 func BenchmarkInsertChain_ring200_memdb(b *testing.B) { 58 benchInsertChain(b, false, genTxRing(200)) 59 } 60 func BenchmarkInsertChain_ring200_diskdb(b *testing.B) { 61 benchInsertChain(b, true, genTxRing(200)) 62 } 63 func BenchmarkInsertChain_ring1000_memdb(b *testing.B) { 64 benchInsertChain(b, false, genTxRing(1000)) 65 } 66 func BenchmarkInsertChain_ring1000_diskdb(b *testing.B) { 67 benchInsertChain(b, true, genTxRing(1000)) 68 } 69 70 var ( 71 // This is the content of the genesis block used by the benchmarks. 72 benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 73 benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey) 74 benchRootFunds = common.BigPow(2, 100) 75 ) 76 77 // genValueTx returns a block generator that includes a single 78 // value-transfer transaction with n bytes of extra data in each 79 // block. 80 func genValueTx(nbytes int) func(int, *BlockGen) { 81 return func(i int, gen *BlockGen) { 82 toaddr := common.Address{} 83 data := make([]byte, nbytes) 84 gas := IntrinsicGas(data, false, false) 85 tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(benchRootKey) 86 gen.AddTx(tx) 87 } 88 } 89 90 var ( 91 ringKeys = make([]*ecdsa.PrivateKey, 1000) 92 ringAddrs = make([]common.Address, len(ringKeys)) 93 ) 94 95 func init() { 96 ringKeys[0] = benchRootKey 97 ringAddrs[0] = benchRootAddr 98 for i := 1; i < len(ringKeys); i++ { 99 ringKeys[i], _ = crypto.GenerateKey() 100 ringAddrs[i] = crypto.PubkeyToAddress(ringKeys[i].PublicKey) 101 } 102 } 103 104 // genTxRing returns a block generator that sends ether in a ring 105 // among n accounts. This is creates n entries in the state database 106 // and fills the blocks with many small transactions. 107 func genTxRing(naccounts int) func(int, *BlockGen) { 108 from := 0 109 return func(i int, gen *BlockGen) { 110 gas := CalcGasLimit(gen.PrevBlock(i - 1)) 111 for { 112 gas.Sub(gas, TxGas) 113 if gas.Cmp(TxGas) < 0 { 114 break 115 } 116 to := (from + 1) % naccounts 117 tx := types.NewTransaction( 118 gen.TxNonce(ringAddrs[from]), 119 ringAddrs[to], 120 benchRootFunds, 121 TxGas, 122 nil, 123 nil, 124 ) 125 tx, _ = tx.WithSigner(types.BasicSigner{}).SignECDSA(ringKeys[from]) 126 gen.AddTx(tx) 127 from = to 128 } 129 } 130 } 131 132 // genUncles generates blocks with two uncle headers. 133 func genUncles(i int, gen *BlockGen) { 134 if i >= 6 { 135 b2 := gen.PrevBlock(i - 6).Header() 136 b2.Extra = []byte("foo") 137 gen.AddUncle(b2) 138 b3 := gen.PrevBlock(i - 6).Header() 139 b3.Extra = []byte("bar") 140 gen.AddUncle(b3) 141 } 142 } 143 144 func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { 145 // Create the database in memory or in a temporary directory. 146 var db ethdb.Database 147 if !disk { 148 db, _ = ethdb.NewMemDatabase() 149 } else { 150 dir, err := ioutil.TempDir("", "eth-core-bench") 151 if err != nil { 152 b.Fatalf("cannot create temporary directory: %v", err) 153 } 154 defer os.RemoveAll(dir) 155 db, err = ethdb.NewLDBDatabase(dir, 128, 128) 156 if err != nil { 157 b.Fatalf("cannot create temporary database: %v", err) 158 } 159 defer db.Close() 160 } 161 162 // Generate a chain of b.N blocks using the supplied block 163 // generator function. 164 genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds}) 165 chain, _ := GenerateChain(DefaultConfigMainnet.ChainConfig, genesis, db, b.N, gen) 166 167 // Time the insertion of the new chain. 168 // State and blocks are stored in the same DB. 169 evmux := new(event.TypeMux) 170 chainman, _ := NewBlockChain(db, DefaultConfigMainnet.ChainConfig, FakePow{}, evmux) 171 defer chainman.Stop() 172 b.ReportAllocs() 173 b.ResetTimer() 174 if res := chainman.InsertChain(chain); res.Error != nil { 175 b.Fatalf("insert error (block %d): %v\n", res.Index, res.Error) 176 } 177 }