github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/neatptc/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/neatlab/neatio/chain/core" 11 "github.com/neatlab/neatio/chain/core/bloombits" 12 "github.com/neatlab/neatio/chain/core/types" 13 "github.com/neatlab/neatio/neatdb" 14 "github.com/neatlab/neatio/network/node" 15 "github.com/neatlab/neatio/utilities/common" 16 "github.com/neatlab/neatio/utilities/common/bitutil" 17 "github.com/neatlab/neatio/utilities/event" 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() + "/neatio/chaindata" 52 fmt.Println("Running bloombits benchmark section size:", sectionSize) 53 54 db, err := neatdb.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 99 } 100 101 d := time.Since(start) 102 fmt.Println("Finished generating bloombits data") 103 fmt.Println(" ", d, "total ", d/time.Duration(cnt*sectionSize), "per block") 104 fmt.Println(" data size:", dataSize, " compressed size:", compSize, " compression ratio:", float64(compSize)/float64(dataSize)) 105 106 fmt.Println("Running filter benchmarks...") 107 start = time.Now() 108 mux := new(event.TypeMux) 109 var backend *testBackend 110 111 for i := 0; i < benchFilterCnt; i++ { 112 if i%20 == 0 { 113 db.Close() 114 db, _ = neatdb.NewLDBDatabase(benchDataDir, 128, 1024) 115 backend = &testBackend{mux, db, cnt, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)} 116 } 117 var addr common.Address 118 addr[0] = byte(i) 119 addr[1] = byte(i / 256) 120 filter := New(backend, 0, int64(cnt*sectionSize-1), []common.Address{addr}, nil) 121 if _, err := filter.Logs(context.Background()); err != nil { 122 b.Error("filter.Find error:", err) 123 } 124 } 125 d = time.Since(start) 126 fmt.Println("Finished running filter benchmarks") 127 fmt.Println(" ", d, "total ", d/time.Duration(benchFilterCnt), "per address", d*time.Duration(1000000)/time.Duration(benchFilterCnt*cnt*sectionSize), "per million blocks") 128 db.Close() 129 } 130 131 func forEachKey(db neatdb.Database, startPrefix, endPrefix []byte, fn func(key []byte)) { 132 it := db.(*neatdb.LDBDatabase).NewIterator() 133 it.Seek(startPrefix) 134 for it.Valid() { 135 key := it.Key() 136 cmpLen := len(key) 137 if len(endPrefix) < cmpLen { 138 cmpLen = len(endPrefix) 139 } 140 if bytes.Compare(key[:cmpLen], endPrefix) == 1 { 141 break 142 } 143 fn(common.CopyBytes(key)) 144 it.Next() 145 } 146 it.Release() 147 } 148 149 var bloomBitsPrefix = []byte("bloomBits-") 150 151 func clearBloomBits(db neatdb.Database) { 152 fmt.Println("Clearing bloombits data...") 153 forEachKey(db, bloomBitsPrefix, bloomBitsPrefix, func(key []byte) { 154 db.Delete(key) 155 }) 156 } 157 158 func BenchmarkNoBloomBits(b *testing.B) { 159 benchDataDir := node.DefaultDataDir() + "/neatio/chaindata" 160 fmt.Println("Running benchmark without bloombits") 161 db, err := neatdb.NewLDBDatabase(benchDataDir, 128, 1024) 162 if err != nil { 163 b.Fatalf("error opening database at %v: %v", benchDataDir, err) 164 } 165 head := core.GetHeadBlockHash(db) 166 if head == (common.Hash{}) { 167 b.Fatalf("chain data not found at %v", benchDataDir) 168 } 169 headNum := core.GetBlockNumber(db, head) 170 171 clearBloomBits(db) 172 173 fmt.Println("Running filter benchmarks...") 174 start := time.Now() 175 mux := new(event.TypeMux) 176 backend := &testBackend{mux, db, 0, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)} 177 filter := New(backend, 0, int64(headNum), []common.Address{{}}, nil) 178 filter.Logs(context.Background()) 179 d := time.Since(start) 180 fmt.Println("Finished running filter benchmarks") 181 fmt.Println(" ", d, "total ", d*time.Duration(1000000)/time.Duration(headNum+1), "per million blocks") 182 db.Close() 183 }