gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/aqua/filters/bench_test.go (about) 1 // Copyright 2018 The aquachain Authors 2 // This file is part of the aquachain library. 3 // 4 // The aquachain 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 aquachain 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 aquachain 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 "gitlab.com/aquachain/aquachain/aqua/event" 27 "gitlab.com/aquachain/aquachain/aquadb" 28 "gitlab.com/aquachain/aquachain/common" 29 "gitlab.com/aquachain/aquachain/common/bitutil" 30 "gitlab.com/aquachain/aquachain/core" 31 "gitlab.com/aquachain/aquachain/core/bloombits" 32 "gitlab.com/aquachain/aquachain/core/types" 33 "gitlab.com/aquachain/aquachain/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() + "/aquachain/chaindata" 68 fmt.Println("Running bloombits benchmark section size:", sectionSize) 69 70 db, err := aquadb.NewLDBDatabase(benchDataDir, 128, 1024) 71 if err != nil { 72 b.Fatalf("error opening database at %v: %v", benchDataDir, err) 73 } 74 head := core.GetHeadBlockHash(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 := core.GetBlockNumber(db, head) 82 if 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 := core.GetCanonicalHash(db, i) 97 header = core.GetHeaderNoVersion(db, hash, i) 98 if header == nil { 99 b.Fatalf("Error creating bloomBits data") 100 } 101 header.Version = 1 102 bc.AddBloom(uint(i-sectionIdx*sectionSize), header.Bloom) 103 } 104 sectionHead := core.GetCanonicalHash(db, (sectionIdx+1)*sectionSize-1) 105 for i := 0; i < types.BloomBitLength; i++ { 106 data, err := bc.Bitset(uint(i)) 107 if err != nil { 108 b.Fatalf("failed to retrieve bitset: %v", err) 109 } 110 comp := bitutil.CompressBytes(data) 111 dataSize += uint64(len(data)) 112 compSize += uint64(len(comp)) 113 core.WriteBloomBits(db, uint(i), sectionIdx, sectionHead, comp) 114 } 115 //if sectionIdx%50 == 0 { 116 // fmt.Println(" section", sectionIdx, "/", cnt) 117 //} 118 } 119 120 d := time.Since(start) 121 fmt.Println("Finished generating bloombits data") 122 fmt.Println(" ", d, "total ", d/time.Duration(cnt*sectionSize), "per block") 123 fmt.Println(" data size:", dataSize, " compressed size:", compSize, " compression ratio:", float64(compSize)/float64(dataSize)) 124 125 fmt.Println("Running filter benchmarks...") 126 start = time.Now() 127 mux := new(event.TypeMux) 128 var backend *testBackend 129 130 for i := 0; i < benchFilterCnt; i++ { 131 if i%20 == 0 { 132 db.Close() 133 db, _ = aquadb.NewLDBDatabase(benchDataDir, 128, 1024) 134 backend = &testBackend{mux, db, cnt, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)} 135 } 136 var addr common.Address 137 addr[0] = byte(i) 138 addr[1] = byte(i / 256) 139 filter := New(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 aquadb.Database, startPrefix, endPrefix []byte, fn func(key []byte)) { 151 it := db.(*aquadb.LDBDatabase).NewIterator() 152 it.Seek(startPrefix) 153 for it.Valid() { 154 key := it.Key() 155 cmpLen := len(key) 156 if len(endPrefix) < cmpLen { 157 cmpLen = len(endPrefix) 158 } 159 if bytes.Compare(key[:cmpLen], endPrefix) == 1 { 160 break 161 } 162 fn(common.CopyBytes(key)) 163 it.Next() 164 } 165 it.Release() 166 } 167 168 var bloomBitsPrefix = []byte("bloomBits-") 169 170 func clearBloomBits(db aquadb.Database) { 171 fmt.Println("Clearing bloombits data...") 172 forEachKey(db, bloomBitsPrefix, bloomBitsPrefix, func(key []byte) { 173 db.Delete(key) 174 }) 175 } 176 177 func BenchmarkNoBloomBits(b *testing.B) { 178 benchDataDir := node.DefaultDataDir() + "/aquachain/chaindata" 179 fmt.Println("Running benchmark without bloombits") 180 db, err := aquadb.NewLDBDatabase(benchDataDir, 128, 1024) 181 if err != nil { 182 b.Fatalf("error opening database at %v: %v", benchDataDir, err) 183 } 184 head := core.GetHeadBlockHash(db) 185 if head == (common.Hash{}) { 186 b.Fatalf("chain data not found at %v", benchDataDir) 187 } 188 headNum := core.GetBlockNumber(db, head) 189 190 clearBloomBits(db) 191 192 fmt.Println("Running filter benchmarks...") 193 start := time.Now() 194 mux := new(event.TypeMux) 195 backend := &testBackend{mux, db, 0, new(event.Feed), new(event.Feed), new(event.Feed), new(event.Feed)} 196 filter := New(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 }