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