github.com/MetalBlockchain/subnet-evm@v0.4.9/eth/filters/bench_test.go (about) 1 // (c) 2019-2022, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2017 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 package filters 28 29 import ( 30 "context" 31 "fmt" 32 "testing" 33 "time" 34 35 "github.com/MetalBlockchain/subnet-evm/core/bloombits" 36 "github.com/MetalBlockchain/subnet-evm/core/rawdb" 37 "github.com/MetalBlockchain/subnet-evm/core/types" 38 "github.com/MetalBlockchain/subnet-evm/ethdb" 39 "github.com/ethereum/go-ethereum/common" 40 "github.com/ethereum/go-ethereum/common/bitutil" 41 "github.com/stretchr/testify/require" 42 ) 43 44 func BenchmarkBloomBits512(b *testing.B) { 45 benchmarkBloomBits(b, 512) 46 } 47 48 func BenchmarkBloomBits1k(b *testing.B) { 49 benchmarkBloomBits(b, 1024) 50 } 51 52 func BenchmarkBloomBits2k(b *testing.B) { 53 benchmarkBloomBits(b, 2048) 54 } 55 56 func BenchmarkBloomBits4k(b *testing.B) { 57 benchmarkBloomBits(b, 4096) 58 } 59 60 func BenchmarkBloomBits8k(b *testing.B) { 61 benchmarkBloomBits(b, 8192) 62 } 63 64 func BenchmarkBloomBits16k(b *testing.B) { 65 benchmarkBloomBits(b, 16384) 66 } 67 68 func BenchmarkBloomBits32k(b *testing.B) { 69 benchmarkBloomBits(b, 32768) 70 } 71 72 const benchFilterCnt = 2000 73 74 func benchmarkBloomBits(b *testing.B, sectionSize uint64) { 75 b.Skip("test disabled: this tests presume (and modify) an existing datadir.") 76 benchDataDir := b.TempDir() + "/subnet-evm/chaindata" 77 b.Log("Running bloombits benchmark section size:", sectionSize) 78 79 db, err := rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) 80 if err != nil { 81 b.Fatalf("error opening database at %v: %v", benchDataDir, err) 82 } 83 head := rawdb.ReadHeadBlockHash(db) 84 if head == (common.Hash{}) { 85 b.Fatalf("chain data not found at %v", benchDataDir) 86 } 87 88 clearBloomBits(db) 89 b.Log("Generating bloombits data...") 90 headNum := rawdb.ReadHeaderNumber(db, head) 91 if headNum == nil || *headNum < sectionSize+512 { 92 b.Fatalf("not enough blocks for running a benchmark") 93 } 94 95 start := time.Now() 96 cnt := (*headNum - 512) / sectionSize 97 var dataSize, compSize uint64 98 for sectionIdx := uint64(0); sectionIdx < cnt; sectionIdx++ { 99 bc, err := bloombits.NewGenerator(uint(sectionSize)) 100 if err != nil { 101 b.Fatalf("failed to create generator: %v", err) 102 } 103 var header *types.Header 104 for i := sectionIdx * sectionSize; i < (sectionIdx+1)*sectionSize; i++ { 105 hash := rawdb.ReadCanonicalHash(db, i) 106 if header = rawdb.ReadHeader(db, hash, i); header == nil { 107 b.Fatalf("Error creating bloomBits data") 108 return 109 } 110 bc.AddBloom(uint(i-sectionIdx*sectionSize), header.Bloom) 111 } 112 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*sectionSize-1) 113 for i := 0; i < types.BloomBitLength; i++ { 114 data, err := bc.Bitset(uint(i)) 115 if err != nil { 116 b.Fatalf("failed to retrieve bitset: %v", err) 117 } 118 comp := bitutil.CompressBytes(data) 119 dataSize += uint64(len(data)) 120 compSize += uint64(len(comp)) 121 rawdb.WriteBloomBits(db, uint(i), sectionIdx, sectionHead, comp) 122 } 123 //if sectionIdx%50 == 0 { 124 // b.Log(" section", sectionIdx, "/", cnt) 125 //} 126 } 127 128 d := time.Since(start) 129 b.Log("Finished generating bloombits data") 130 b.Log(" ", d, "total ", d/time.Duration(cnt*sectionSize), "per block") 131 b.Log(" data size:", dataSize, " compressed size:", compSize, " compression ratio:", float64(compSize)/float64(dataSize)) 132 133 b.Log("Running filter benchmarks...") 134 start = time.Now() 135 136 var ( 137 backend *testBackend 138 sys *FilterSystem 139 ) 140 for i := 0; i < benchFilterCnt; i++ { 141 if i%20 == 0 { 142 db.Close() 143 db, _ = rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) 144 backend = &testBackend{db: db, sections: cnt} 145 sys = NewFilterSystem(backend, Config{}) 146 } 147 var addr common.Address 148 addr[0] = byte(i) 149 addr[1] = byte(i / 256) 150 filter, err := sys.NewRangeFilter(0, int64(cnt*sectionSize-1), []common.Address{addr}, nil) 151 require.NoError(b, err) 152 if _, err := filter.Logs(context.Background()); err != nil { 153 b.Error("filter.Logs error:", err) 154 } 155 } 156 157 d = time.Since(start) 158 b.Log("Finished running filter benchmarks") 159 b.Log(" ", d, "total ", d/time.Duration(benchFilterCnt), "per address", d*time.Duration(1000000)/time.Duration(benchFilterCnt*cnt*sectionSize), "per million blocks") 160 db.Close() 161 } 162 163 //nolint:unused 164 func clearBloomBits(db ethdb.Database) { 165 var bloomBitsPrefix = []byte("bloomBits-") 166 fmt.Println("Clearing bloombits data...") 167 it := db.NewIterator(bloomBitsPrefix, nil) 168 for it.Next() { 169 db.Delete(it.Key()) 170 } 171 it.Release() 172 } 173 174 func BenchmarkNoBloomBits(b *testing.B) { 175 b.Skip("test disabled: this tests presume (and modify) an existing datadir.") 176 benchDataDir := b.TempDir() + "/subnet-evm/chaindata" 177 b.Log("Running benchmark without bloombits") 178 db, err := rawdb.NewLevelDBDatabase(benchDataDir, 128, 1024, "", false) 179 if err != nil { 180 b.Fatalf("error opening database at %v: %v", benchDataDir, err) 181 } 182 head := rawdb.ReadHeadBlockHash(db) 183 if head == (common.Hash{}) { 184 b.Fatalf("chain data not found at %v", benchDataDir) 185 } 186 headNum := rawdb.ReadHeaderNumber(db, head) 187 188 clearBloomBits(db) 189 190 _, sys := newTestFilterSystem(b, db, Config{}) 191 192 b.Log("Running filter benchmarks...") 193 start := time.Now() 194 filter, err := sys.NewRangeFilter(0, int64(*headNum), []common.Address{{}}, nil) 195 require.NoError(b, err) 196 filter.Logs(context.Background()) 197 d := time.Since(start) 198 b.Log("Finished running filter benchmarks") 199 b.Log(" ", d, "total ", d*time.Duration(1000000)/time.Duration(*headNum+1), "per million blocks") 200 db.Close() 201 }