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