github.com/theQRL/go-zond@v0.2.1/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 "math/big" 21 "testing" 22 23 "github.com/theQRL/go-qrllib/dilithium" 24 "github.com/theQRL/go-zond/common" 25 "github.com/theQRL/go-zond/common/math" 26 "github.com/theQRL/go-zond/consensus/beacon" 27 "github.com/theQRL/go-zond/core/rawdb" 28 "github.com/theQRL/go-zond/core/types" 29 "github.com/theQRL/go-zond/core/vm" 30 "github.com/theQRL/go-zond/crypto/pqcrypto" 31 "github.com/theQRL/go-zond/params" 32 "github.com/theQRL/go-zond/zonddb" 33 ) 34 35 func BenchmarkInsertChain_empty_memdb(b *testing.B) { 36 benchInsertChain(b, false, nil) 37 } 38 func BenchmarkInsertChain_empty_diskdb(b *testing.B) { 39 benchInsertChain(b, true, nil) 40 } 41 func BenchmarkInsertChain_valueTx_memdb(b *testing.B) { 42 benchInsertChain(b, false, genValueTx(0)) 43 } 44 func BenchmarkInsertChain_valueTx_diskdb(b *testing.B) { 45 benchInsertChain(b, true, genValueTx(0)) 46 } 47 func BenchmarkInsertChain_valueTx_100kB_memdb(b *testing.B) { 48 benchInsertChain(b, false, genValueTx(100*1024)) 49 } 50 func BenchmarkInsertChain_valueTx_100kB_diskdb(b *testing.B) { 51 benchInsertChain(b, true, genValueTx(100*1024)) 52 } 53 func BenchmarkInsertChain_ring200_memdb(b *testing.B) { 54 benchInsertChain(b, false, genTxRing(200)) 55 } 56 func BenchmarkInsertChain_ring200_diskdb(b *testing.B) { 57 benchInsertChain(b, true, genTxRing(200)) 58 } 59 func BenchmarkInsertChain_ring1000_memdb(b *testing.B) { 60 benchInsertChain(b, false, genTxRing(1000)) 61 } 62 func BenchmarkInsertChain_ring1000_diskdb(b *testing.B) { 63 benchInsertChain(b, true, genTxRing(1000)) 64 } 65 66 var ( 67 // This is the content of the genesis block used by the benchmarks. 68 benchRootKey, _ = pqcrypto.HexToDilithium("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 69 benchRootAddr = common.Address(benchRootKey.GetAddress()) 70 benchRootFunds = math.BigPow(2, 200) 71 ) 72 73 // genValueTx returns a block generator that includes a single 74 // value-transfer transaction with n bytes of extra data in each 75 // block. 76 func genValueTx(nbytes int) func(int, *BlockGen) { 77 return func(i int, gen *BlockGen) { 78 toaddr := common.Address{} 79 data := make([]byte, nbytes) 80 gas, _ := IntrinsicGas(data, nil, false) 81 signer := types.MakeSigner(gen.config) 82 baseFee := big.NewInt(0) 83 if gen.header.BaseFee != nil { 84 baseFee = gen.header.BaseFee 85 } 86 tx, _ := types.SignNewTx(benchRootKey, signer, &types.DynamicFeeTx{ 87 Nonce: gen.TxNonce(benchRootAddr), 88 To: &toaddr, 89 Value: big.NewInt(1), 90 Gas: gas, 91 Data: data, 92 GasFeeCap: baseFee, 93 }) 94 gen.AddTx(tx) 95 } 96 } 97 98 var ( 99 ringKeys = make([]*dilithium.Dilithium, 1000) 100 ringAddrs = make([]common.Address, len(ringKeys)) 101 ) 102 103 func init() { 104 ringKeys[0] = benchRootKey 105 ringAddrs[0] = benchRootAddr 106 for i := 1; i < len(ringKeys); i++ { 107 ringKeys[i], _ = pqcrypto.GenerateDilithiumKey() 108 ringAddrs[i] = ringKeys[i].GetAddress() 109 } 110 } 111 112 // genTxRing returns a block generator that sends ether in a ring 113 // among n accounts. This is creates n entries in the state database 114 // and fills the blocks with many small transactions. 115 func genTxRing(naccounts int) func(int, *BlockGen) { 116 from := 0 117 availableFunds := new(big.Int).Set(benchRootFunds) 118 return func(i int, gen *BlockGen) { 119 block := gen.PrevBlock(i - 1) 120 gas := block.GasLimit() 121 baseFee := big.NewInt(0) 122 if gen.header.BaseFee != nil { 123 baseFee = gen.header.BaseFee 124 } 125 signer := types.MakeSigner(gen.config) 126 for { 127 gas -= params.TxGas 128 if gas < params.TxGas { 129 break 130 } 131 to := (from + 1) % naccounts 132 burn := new(big.Int).SetUint64(params.TxGas) 133 burn.Mul(burn, gen.header.BaseFee) 134 availableFunds.Sub(availableFunds, burn) 135 if availableFunds.Cmp(big.NewInt(1)) < 0 { 136 panic("not enough funds") 137 } 138 tx, err := types.SignNewTx(ringKeys[from], signer, 139 &types.DynamicFeeTx{ 140 Nonce: gen.TxNonce(ringAddrs[from]), 141 To: &ringAddrs[to], 142 Value: availableFunds, 143 Gas: params.TxGas, 144 GasFeeCap: baseFee, 145 }) 146 if err != nil { 147 panic(err) 148 } 149 gen.AddTx(tx) 150 from = to 151 } 152 } 153 } 154 155 func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { 156 // Create the database in memory or in a temporary directory. 157 var db zonddb.Database 158 var err error 159 if !disk { 160 db = rawdb.NewMemoryDatabase() 161 } else { 162 dir := b.TempDir() 163 db, err = rawdb.NewLevelDBDatabase(dir, 128, 128, "", false) 164 if err != nil { 165 b.Fatalf("cannot create temporary database: %v", err) 166 } 167 defer db.Close() 168 } 169 170 // Generate a chain of b.N blocks using the supplied block 171 // generator function. 172 gspec := &Genesis{ 173 Config: params.TestChainConfig, 174 Alloc: GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}}, 175 } 176 _, chain, _ := GenerateChainWithGenesis(gspec, beacon.NewFaker(), b.N, gen) 177 178 // Time the insertion of the new chain. 179 // State and blocks are stored in the same DB. 180 chainman, _ := NewBlockChain(db, nil, gspec, beacon.NewFaker(), vm.Config{}, nil) 181 defer chainman.Stop() 182 b.ReportAllocs() 183 b.ResetTimer() 184 if i, err := chainman.InsertChain(chain); err != nil { 185 b.Fatalf("insert error (block %d): %v\n", i, err) 186 } 187 } 188 189 func BenchmarkChainRead_header_10k(b *testing.B) { 190 benchReadChain(b, false, 10000) 191 } 192 func BenchmarkChainRead_full_10k(b *testing.B) { 193 benchReadChain(b, true, 10000) 194 } 195 func BenchmarkChainRead_header_100k(b *testing.B) { 196 benchReadChain(b, false, 100000) 197 } 198 func BenchmarkChainRead_full_100k(b *testing.B) { 199 benchReadChain(b, true, 100000) 200 } 201 func BenchmarkChainRead_header_500k(b *testing.B) { 202 benchReadChain(b, false, 500000) 203 } 204 func BenchmarkChainRead_full_500k(b *testing.B) { 205 benchReadChain(b, true, 500000) 206 } 207 func BenchmarkChainWrite_header_10k(b *testing.B) { 208 benchWriteChain(b, false, 10000) 209 } 210 func BenchmarkChainWrite_full_10k(b *testing.B) { 211 benchWriteChain(b, true, 10000) 212 } 213 func BenchmarkChainWrite_header_100k(b *testing.B) { 214 benchWriteChain(b, false, 100000) 215 } 216 func BenchmarkChainWrite_full_100k(b *testing.B) { 217 benchWriteChain(b, true, 100000) 218 } 219 func BenchmarkChainWrite_header_500k(b *testing.B) { 220 benchWriteChain(b, false, 500000) 221 } 222 func BenchmarkChainWrite_full_500k(b *testing.B) { 223 benchWriteChain(b, true, 500000) 224 } 225 226 // makeChainForBench writes a given number of headers or empty blocks/receipts 227 // into a database. 228 func makeChainForBench(db zonddb.Database, full bool, count uint64) { 229 var hash common.Hash 230 for n := uint64(0); n < count; n++ { 231 header := &types.Header{ 232 Coinbase: common.Address{}, 233 Number: big.NewInt(int64(n)), 234 ParentHash: hash, 235 TxHash: types.EmptyTxsHash, 236 ReceiptHash: types.EmptyReceiptsHash, 237 } 238 hash = header.Hash() 239 240 rawdb.WriteHeader(db, header) 241 rawdb.WriteCanonicalHash(db, hash, n) 242 243 if n == 0 { 244 rawdb.WriteChainConfig(db, hash, params.AllBeaconProtocolChanges) 245 } 246 rawdb.WriteHeadHeaderHash(db, hash) 247 248 if full || n == 0 { 249 block := types.NewBlockWithHeader(header) 250 rawdb.WriteBody(db, hash, n, block.Body()) 251 rawdb.WriteReceipts(db, hash, n, nil) 252 rawdb.WriteHeadBlockHash(db, hash) 253 } 254 } 255 } 256 257 func benchWriteChain(b *testing.B, full bool, count uint64) { 258 for i := 0; i < b.N; i++ { 259 dir := b.TempDir() 260 db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) 261 if err != nil { 262 b.Fatalf("error opening database at %v: %v", dir, err) 263 } 264 makeChainForBench(db, full, count) 265 db.Close() 266 } 267 } 268 269 func benchReadChain(b *testing.B, full bool, count uint64) { 270 dir := b.TempDir() 271 272 db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) 273 if err != nil { 274 b.Fatalf("error opening database at %v: %v", dir, err) 275 } 276 makeChainForBench(db, full, count) 277 db.Close() 278 cacheConfig := *defaultCacheConfig 279 cacheConfig.TrieDirtyDisabled = true 280 281 b.ReportAllocs() 282 b.ResetTimer() 283 284 for i := 0; i < b.N; i++ { 285 db, err := rawdb.NewLevelDBDatabase(dir, 128, 1024, "", false) 286 if err != nil { 287 b.Fatalf("error opening database at %v: %v", dir, err) 288 } 289 chain, err := NewBlockChain(db, &cacheConfig, nil, beacon.NewFaker(), vm.Config{}, nil) 290 if err != nil { 291 b.Fatalf("error creating chain: %v", err) 292 } 293 294 for n := uint64(0); n < count; n++ { 295 header := chain.GetHeaderByNumber(n) 296 if full { 297 hash := header.Hash() 298 rawdb.ReadBody(db, hash, n) 299 rawdb.ReadReceipts(db, hash, n, header.Time, chain.Config()) 300 } 301 } 302 chain.Stop() 303 db.Close() 304 } 305 }