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