github.com/bcskill/bcschain/v3@v3.4.9-beta2/eth/filters/bench_test.go (about) 1 // Copyright 2017 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 filters 18 19 import ( 20 "bytes" 21 "context" 22 "fmt" 23 "testing" 24 "time" 25 26 "github.com/bcskill/bcschain/v3/common" 27 "github.com/bcskill/bcschain/v3/common/bitutil" 28 "github.com/bcskill/bcschain/v3/core/bloombits" 29 "github.com/bcskill/bcschain/v3/core/rawdb" 30 "github.com/bcskill/bcschain/v3/core/types" 31 "github.com/bcskill/bcschain/v3/ethdb" 32 "github.com/bcskill/bcschain/v3/node" 33 ) 34 35 func BenchmarkBloomBits512(b *testing.B) { 36 benchmarkBloomBits(b, 512) 37 } 38 39 func BenchmarkBloomBits1k(b *testing.B) { 40 benchmarkBloomBits(b, 1024) 41 } 42 43 func BenchmarkBloomBits2k(b *testing.B) { 44 benchmarkBloomBits(b, 2048) 45 } 46 47 func BenchmarkBloomBits4k(b *testing.B) { 48 benchmarkBloomBits(b, 4096) 49 } 50 51 func BenchmarkBloomBits8k(b *testing.B) { 52 benchmarkBloomBits(b, 8192) 53 } 54 55 func BenchmarkBloomBits16k(b *testing.B) { 56 benchmarkBloomBits(b, 16384) 57 } 58 59 func BenchmarkBloomBits32k(b *testing.B) { 60 benchmarkBloomBits(b, 32768) 61 } 62 63 const benchFilterCnt = 2000 64 65 func benchmarkBloomBits(b *testing.B, sectionSize uint64) { 66 benchDataDir := node.DefaultDataDir() + "/geth/chaindata" 67 fmt.Println("Running bloombits benchmark section size:", sectionSize) 68 69 db := ethdb.NewDB(benchDataDir) 70 if err := db.Open(); err != nil { 71 b.Fatalf("error opening database at %v: %v", benchDataDir, err) 72 } 73 head := rawdb.ReadHeadBlockHash(db.GlobalTable()) 74 if head == (common.Hash{}) { 75 b.Fatalf("chain data not found at %v", benchDataDir) 76 } 77 78 clearBloomBits(db) 79 fmt.Println("Generating bloombits data...") 80 headNum := rawdb.ReadHeaderNumber(db.GlobalTable(), head) 81 if headNum == nil || *headNum < sectionSize+512 { 82 b.Fatalf("not enough blocks for running a benchmark") 83 } 84 85 start := time.Now() 86 cnt := (*headNum - 512) / sectionSize 87 var dataSize, compSize uint64 88 for sectionIdx := uint64(0); sectionIdx < cnt; sectionIdx++ { 89 bc, err := bloombits.NewGenerator(uint(sectionSize)) 90 if err != nil { 91 b.Fatalf("failed to create generator: %v", err) 92 } 93 var header *types.Header 94 for i := sectionIdx * sectionSize; i < (sectionIdx+1)*sectionSize; i++ { 95 hash := rawdb.ReadCanonicalHash(db, i) 96 header = rawdb.ReadHeader(db.HeaderTable(), hash, i) 97 if header == nil { 98 b.Fatalf("Error creating bloomBits data") 99 } 100 bc.AddBloom(uint(i-sectionIdx*sectionSize), header.Bloom) 101 } 102 sectionHead := rawdb.ReadCanonicalHash(db, (sectionIdx+1)*sectionSize-1) 103 for i := 0; i < types.BloomBitLength; i++ { 104 data, err := bc.Bitset(uint(i)) 105 if err != nil { 106 b.Fatalf("failed to retrieve bitset: %v", err) 107 } 108 comp := bitutil.CompressBytes(data) 109 dataSize += uint64(len(data)) 110 compSize += uint64(len(comp)) 111 rawdb.WriteBloomBits(db.GlobalTable(), uint(i), sectionIdx, sectionHead, comp) 112 } 113 //if sectionIdx%50 == 0 { 114 // fmt.Println(" section", sectionIdx, "/", cnt) 115 //} 116 } 117 118 d := time.Since(start) 119 fmt.Println("Finished generating bloombits data") 120 fmt.Println(" ", d, "total ", d/time.Duration(cnt*sectionSize), "per block") 121 fmt.Println(" data size:", dataSize, " compressed size:", compSize, " compression ratio:", float64(compSize)/float64(dataSize)) 122 123 fmt.Println("Running filter benchmarks...") 124 start = time.Now() 125 var backend *testBackend 126 127 for i := 0; i < benchFilterCnt; i++ { 128 if i%20 == 0 { 129 db.Close() 130 db := ethdb.NewDB(benchDataDir) 131 if err := db.Open(); err != nil { 132 b.Fatal(err) 133 } 134 backend = &testBackend{db: db, sections: cnt} 135 } 136 var addr common.Address 137 addr[0] = byte(i) 138 addr[1] = byte(i / 256) 139 filter := NewRangeFilter(backend, 0, int64(cnt*sectionSize-1), []common.Address{addr}, nil) 140 if _, err := filter.Logs(context.Background()); err != nil { 141 b.Error("filter.Find error:", err) 142 } 143 } 144 d = time.Since(start) 145 fmt.Println("Finished running filter benchmarks") 146 fmt.Println(" ", d, "total ", d/time.Duration(benchFilterCnt), "per address", d*time.Duration(1000000)/time.Duration(benchFilterCnt*cnt*sectionSize), "per million blocks") 147 db.Close() 148 } 149 150 func forEachKey(db common.Database, startPrefix, endPrefix []byte, fn func(key []byte)) { 151 tbl := db.GlobalTable().(*ethdb.Table) 152 it := tbl.ActiveSegment().(*ethdb.LDBSegment).LDB().NewIterator(nil, nil) 153 it.Seek(startPrefix) 154 for it.Valid() { 155 key := it.Key() 156 cmpLen := len(key) 157 if len(endPrefix) < cmpLen { 158 cmpLen = len(endPrefix) 159 } 160 if bytes.Compare(key[:cmpLen], endPrefix) == 1 { 161 break 162 } 163 fn(common.CopyBytes(key)) 164 it.Next() 165 } 166 it.Release() 167 } 168 169 var bloomBitsPrefix = []byte("bloomBits-") 170 171 func clearBloomBits(db common.Database) { 172 fmt.Println("Clearing bloombits data...") 173 forEachKey(db, bloomBitsPrefix, bloomBitsPrefix, func(key []byte) { 174 db.GlobalTable().Delete(key) 175 }) 176 } 177 178 func BenchmarkNoBloomBits(b *testing.B) { 179 benchDataDir := node.DefaultDataDir() + "/geth/chaindata" 180 fmt.Println("Running benchmark without bloombits") 181 db := ethdb.NewDB(benchDataDir) 182 if err := db.Open(); err != nil { 183 b.Fatalf("error opening database at %v: %v", benchDataDir, err) 184 } 185 head := rawdb.ReadHeadBlockHash(db.GlobalTable()) 186 if head == (common.Hash{}) { 187 b.Fatalf("chain data not found at %v", benchDataDir) 188 } 189 headNum := rawdb.ReadHeaderNumber(db.GlobalTable(), head) 190 191 clearBloomBits(db) 192 193 fmt.Println("Running filter benchmarks...") 194 start := time.Now() 195 backend := &testBackend{db: db} 196 filter := NewRangeFilter(backend, 0, int64(*headNum), []common.Address{{}}, nil) 197 filter.Logs(context.Background()) 198 d := time.Since(start) 199 fmt.Println("Finished running filter benchmarks") 200 fmt.Println(" ", d, "total ", d*time.Duration(1000000)/time.Duration(*headNum+1), "per million blocks") 201 db.Close() 202 }