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