github.com/klaytn/klaytn@v1.10.2/tests/benchmarks/bloomfilter_test.go (about) 1 // Copyright 2018 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn 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 klaytn 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 klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package benchmarks 18 19 import ( 20 "bytes" 21 "math/big" 22 "testing" 23 24 "github.com/klaytn/klaytn/blockchain/types" 25 "github.com/syndtr/goleveldb/leveldb/filter" 26 "github.com/syndtr/goleveldb/leveldb/util" 27 ) 28 29 var addrs = []string{ 30 "0x229E467d46913DfdB70D8f13c2461665F7FeB2a9", 31 "0x312446899c6d5b05AD45a71a762bba7D0DEa074a", 32 "0x6705CeeE1e40CC5120170ea022e4f91de63fB379", 33 "0x2b789F8b96D2D8cd95814754032e6183b898DDcA", 34 "0x26Facf5aA382Eb51dCCa1742Eb0a3cc9d8FE9392", 35 "0x545CD2e0E3ddf6F5632439b1e655B6d0e9a73B8b", 36 "0x34f9A1bE6A66177395469f6E982d4563D0870827", 37 "0x2bf3B29c19C9EF545E27f6085DB9b9B26Db8B656", 38 "0xA02732AaFAF6883278339A22039CaFac5e059282", 39 "0x1d3cdb28cf75d00b63E9e95b2bcBda767ea7d231", 40 "0x756C7bf861b64cf5F1B23a231a90d4D096126A68", 41 "0x66ee129A97D1C87e492d50B34569b8324F8600DF", 42 "0x3f46db8390BC22FAf7f34675B58d35b959C8e0C9", 43 "0x30E06cebB43b776091EFfd1dE182e36AF2eb4FA3", 44 "0x230e7142Fd5FF14d8A177c6E6fbF76aadbF4bC5F", 45 "0xE0e3C8752b368c921b3c520797E0bBC2EB50E7Ed", 46 "0xCC7d575D6d538A987082ad5a1DCAe9e1c469Bd95", 47 "0xCD2DC73D736c31D7aa98209dD4068979F19e486B", 48 "0xC97e706e31c3E22E8d17C62Ef886046C8BC09864", 49 "0x48a3f5Af534C01Ad35aFB2b86fAE3e0cDd61f6F4", 50 "0xa26B94C2c708A76DA440Dc245Dc03e031c1AfD05", 51 "0x30831D05a46f5C62F209Fe0524d1a9F731d74247", 52 "0x7fA4780fAe30D9a0b0e2131F993598C19524f7D1", 53 "0xED18B2a4C14BA903ad3156FBE5306a23D5594218", 54 "0x9B80efC4eD1EC0B012526cb3407758ddD6b9B640", 55 "0x438A7fDC25b0a8880c51529A4C1459B32405496B", 56 "0xe5cA882eB33B9fB1c3D33FE482b79Db3D2f4B473", 57 "0x21f58c4d24CE65279a9457bc96c0ABC2a581208c", 58 "0x6288bfB0da903a4eb4641dB008C736588Cd60DCB", 59 "0xc10320Af5D9CC75ab00e6BED91dcA817f2A4cBDf", 60 "0x66307bC0A5Db3Cd87bcD5fc5281bdDD937D09b6D", 61 "0x782ED08B2C25A3979e32c15d191B00f20f5A80d7", 62 "0xD6E3cdb9Bb23ef2E1268722e2e91c0509e8E9fA7", 63 "0x2D39aB465327e1bD7962F4eaCD75843a555140A1", 64 "0x3c8B900D9E8ee88232Dc836F039a88d36e8446cB", 65 "0x629dd6B9B57D4CeA689804373bA6B562D984cD93", 66 "0x6381F02d3Da9823EBD7FF1BF2c198Fb5F0Ff8460", 67 "0xd24151F529a594Eb0fE7A751261A2CD39ec76845", 68 "0xAFdaeDf63E67228B0ddc472F2266B0715779F852", 69 "0x9EbD57f9611eD745C08B00b6cc7c657C910e3c11", 70 "0xF648E5500218a5012FBE2E65c184d136E58aA2ED", 71 "0x76fD23E0995BfAD8E3896827D471478C122541Ea", 72 "0xEe562Fef72128e530C0Ae4C86F16D714eAd1A07E", 73 "0x37197FFD3b1c0BE35103D883519ECe09Af15Ca35", 74 "0xf94eC4C22724557d94e69f67B9D3567eD65f3d37", 75 "0xfA50A75cEAACceB321e3f92b293e121737C79Ea6", 76 "0x9DFF8E6327D692a31Bb2fB8dc68F88D054b4aa3a", 77 "0xD569e27092a0CB89B6bf3E7D645cb6c9a350474a", 78 "0x963cF4eA4AAFA550Ba100F1e22703b80a1DBdFE1", 79 "0x05B12922B33D8e294e8C70e49BC1DAb261C1E517", 80 "0x50dc2304b1e1A6bC6619e7Eb523b6D2cdf255961", 81 "0xbdB837580481862e2b12336f4A26Af4b23A6dF30", 82 "0xda1d187aEEdfBF91E6D8e62bBF568C3D96FA3af1", 83 "0xAC99De0933A6124e3ac260706C1d34f0651f27A5", 84 "0x2964d12F17742FBAccAB7FCE9a790fA168a87325", 85 "0x88E39847786D39A7cdAA7Aa53e9E9B1A023ab844", 86 "0x6d981748AC668B68d803DA5C69562F4ae6A1452d", 87 "0xf886C291a646b6fDc54441D9BEEd11a9f78AEB15", 88 "0xF0f54c01Fe4D2363C1D2F377d8Cca525c6C130dC", 89 "0x8650a24e65d42a32bda84AC9DD02B8902eA821c2", 90 "0x70EcB9089533C3c2Ea53E7Df300F0A33f7bFC61b", 91 "0x56a619032B2999D0e104519bD0bb74B0c46E378E", 92 "0xfd80977D9550A5B5319f7dadb3674D29193b8C60", 93 "0xaFBAb54E1999eC71086fac001deef33d4E156cAE", 94 "0xd1448E5CFC6440c2437912d51f2080c421c2C638", 95 "0x7D13Fb871E42556D2Dcf5b6A6126b68345Cc347A", 96 "0x7849729e108631224c197dB4C1EBf272D98F793e", 97 "0x3b8822D9e34F1090670c64F99d4cb6a2b4795FAa", 98 "0x09271289E82d292Bb8d2DAb48eb7c5ABB591A630", 99 "0xaE21c5ACE28dD7393f770b5218aB9bAea5456352", 100 "0x84F4351c067dd981d6e8Db6dEC96bA5aed0CF010", 101 "0xd941E547Ce39d654505cFB5211D6B87ff2811519", 102 "0x7069dc629305D5f02fAdB542c0634f3BD124137E", 103 "0x4ee5Ef6fcC0E1A15b84547101064d70dD2AD22df", 104 "0x956171aEeb695A125b770D5AAD6C6c0Ceb6bdBe8", 105 "0x395FbF1dD980c8Cf10586D0df4945016526BE786", 106 "0xAb456bc354b1003F10BeD63C001CaeE55b4Be675", 107 "0x277570CDcf52dB43E7F307CbF1E58748f5F3f8E8", 108 "0x5F048d235ddc6E727C0B9D1FF11510767Eb172Cb", 109 "0x29299F84810af7e005880B65f96485e2251051e5", 110 "0xA9e0e5d8B704Ec921E8a55c92353E23910bAdbC8", 111 "0x9C7ee419706779C4233C0e6a547f9a67AF1AE04E", 112 "0xDb91330c323961937b73586E6Cbd19a2642e08a9", 113 "0x4e2bB263D843cCDeeB8c3269bca732B9158FaCA1", 114 "0xC3c33Ec0C89F0E64F84F3D561BF6259BedB28A43", 115 "0x56a2639569035159BfC6BDEb1654F4FD57a016FB", 116 "0xA747aba1bc48eAb2e0e68a310C81F0cD679cAf74", 117 "0x6e86f162Be0117f9F921D4328f2DC8ada2d345B0", 118 "0x088A4f7d637998d8d7ac53D2f5e9Bf89C0b308eF", 119 "0xda90F4bBa7ACE86cFB097d90024A58fB59c7D5b5", 120 "0x974ed4327fDb8786A3C543410858840DD1674631", 121 "0xe92Be80a0bb0749d30544964d7E4437cF9b02f57", 122 "0x0F07efB587C192BF4666990F72AD7f853e7F85C6", 123 "0x4984c77B4752B38B86E2CBBAD34625c763c2DD57", 124 "0x3aB6E0759a9d5Ba5EdD15A69F154dE57998829ee", 125 "0xbcF2Da0fc549e1160555104EE24158B866Dec35C", 126 "0xed0cB5774014bc66F03dfDdfeEf9790e2097A320", 127 "0x9c8A0e62E4b48a9aB8f4f8cd5A31fF36Ddbdf82F", 128 "0xf284f64f865d379f06b2e9D7d5714DFA3860e8de", 129 "0x7647D15CC3C58FCeD12a8cB40c5603345aD7f37d", 130 } 131 132 var badAddrs = []string{ 133 "0xc4E9fe2E3f040964770Fa0A2AE2f549292F318fc", 134 "0x5FdC97cD5ae70500B8A01b474c0f77a0c3845575", 135 "0xEB5cFBDd1c69C05E7FD12b214c07141F8413fe31", 136 "0x0F2A66C73fbbff5fD21Cd4F3ACb0491B61c58bA9", 137 "0x80F26DC89A19428E79156E66753E602e4b421dA8", 138 "0x277570CDcf52dB43E7F307CbF1E58748f5F3f8E7", 139 "0x5F048d235ddc6E727C0B9D1FF11510767Eb172C0", 140 "0x29299F84810af7e005880B65f96485e2251051e0", 141 "0xA9e0e5d8B704Ec921E8a55c92353E23910bAdbC6", 142 "0x9C7ee419706779C4233C0e6a547f9a67AF1AE04A", 143 } 144 145 const bitsPerKey = 16 146 147 type testOption struct { 148 testAddrs []string 149 expected bool 150 msg string 151 } 152 153 var lookupBenchmarks = [...]struct { 154 name string 155 opt testOption 156 }{ 157 {"True", testOption{addrs, true, "expected"}}, 158 {"False", testOption{badAddrs, false, "did not expect"}}, 159 } 160 161 var compareBenchmarks = [...]struct { 162 name string 163 opt testOption 164 }{ 165 {"Same", testOption{addrs, true, "to be the same as"}}, 166 {"Different", testOption{badAddrs, false, "to be different from"}}, 167 } 168 169 var bitandBenchmarks = [...]struct { 170 name string 171 opt testOption 172 }{ 173 {"True", testOption{addrs, true, "expected"}}, 174 {"False", testOption{badAddrs, false, "did not expect"}}, 175 } 176 177 func bloomBitAND(bloom1, bloom2 types.Bloom) types.Bloom { 178 bloom1Bytes := bloom1.Bytes() 179 bloom2Bytes := bloom2.Bytes() 180 var resultBytes types.Bloom 181 182 for i := 0; i < types.BloomByteLength; i++ { 183 resultBytes[i] = bloom1Bytes[i] & bloom2Bytes[i] 184 } 185 186 return resultBytes 187 } 188 189 func ldbBloomBitAND(bloom1, bloom2 []byte) []byte { 190 lenFilter := len(bloom1) 191 resultBytes := make([]byte, lenFilter) 192 193 for i := 0; i < lenFilter; i++ { 194 resultBytes[i] = bloom1[i] & bloom2[i] 195 } 196 197 return resultBytes 198 } 199 200 func Benchmark_Map_Add(b *testing.B) { 201 toset := make(map[string]int) 202 numAddrs := len(addrs) 203 204 b.ResetTimer() 205 for k := 0; k < b.N; k++ { 206 addr := addrs[k%numAddrs] 207 toset[addr] = k 208 } 209 } 210 211 func benchmark_Map_Lookup(b *testing.B, toset map[string]int, opt *testOption) { 212 numAddrs := len(opt.testAddrs) 213 214 b.ResetTimer() 215 for k := 0; k < b.N; k++ { 216 addr := opt.testAddrs[k%numAddrs] 217 if _, exists := toset[addr]; exists != opt.expected { 218 b.Error(opt.msg, addr, "to test true") 219 } 220 } 221 } 222 223 func Benchmark_Map_Lookup(b *testing.B) { 224 toset := make(map[string]int) 225 for i, addr := range addrs { 226 toset[addr] = i 227 } 228 229 for _, bm := range lookupBenchmarks { 230 b.Run(bm.name, func(b *testing.B) { 231 benchmark_Map_Lookup(b, toset, &bm.opt) 232 }) 233 } 234 } 235 236 func Benchmark_Bloom_Add(b *testing.B) { 237 numAddrs := len(addrs) 238 239 b.ResetTimer() 240 for k := 0; k < b.N/numAddrs; k++ { 241 var bloom types.Bloom 242 for _, addr := range addrs { 243 bloom.Add(new(big.Int).SetBytes([]byte(addr))) 244 } 245 } 246 } 247 248 func benchmark_Bloom_Lookup(b *testing.B, bloom types.Bloom, opt *testOption) { 249 numAddrs := len(opt.testAddrs) 250 251 b.ResetTimer() 252 for k := 0; k < b.N; k++ { 253 addr := opt.testAddrs[k%numAddrs] 254 if bloom.TestBytes([]byte(addr)) != opt.expected { 255 b.Error(opt.msg, addr, "to test true") 256 } 257 } 258 } 259 260 func Benchmark_Bloom_Lookup(b *testing.B) { 261 var bloom types.Bloom 262 for _, addr := range addrs { 263 bloom.Add(new(big.Int).SetBytes([]byte(addr))) 264 } 265 266 for _, bm := range lookupBenchmarks { 267 b.Run(bm.name, func(b *testing.B) { 268 benchmark_Bloom_Lookup(b, bloom, &bm.opt) 269 }) 270 } 271 } 272 273 func benchmark_Bloom_Compare(b *testing.B, bloom1 types.Bloom, opt *testOption) { 274 var bloom2 types.Bloom 275 for _, addr := range opt.testAddrs { 276 bloom2.Add(new(big.Int).SetBytes([]byte(addr))) 277 } 278 279 b.ResetTimer() 280 for k := 0; k < b.N; k++ { 281 if (bloom1 == bloom2) != opt.expected { 282 b.Error("expected", bloom2.Big(), opt.msg, bloom1.Big()) 283 } 284 } 285 } 286 287 func Benchmark_Bloom_Compare(b *testing.B) { 288 var bloom1 types.Bloom 289 for _, addr := range addrs { 290 bloom1.Add(new(big.Int).SetBytes([]byte(addr))) 291 } 292 293 for _, bm := range compareBenchmarks { 294 b.Run(bm.name, func(b *testing.B) { 295 benchmark_Bloom_Compare(b, bloom1, &bm.opt) 296 }) 297 } 298 } 299 300 func benchmark_Bloom_BitAND(b *testing.B, bloom1 types.Bloom, opt *testOption) { 301 var bloom2 types.Bloom 302 if len(opt.testAddrs) > 0 { 303 bloom2.Add(new(big.Int).SetBytes([]byte(opt.testAddrs[0]))) 304 } 305 306 b.ResetTimer() 307 for k := 0; k < b.N; k++ { 308 result := bloomBitAND(bloom1, bloom2) 309 if (result == bloom2) != opt.expected { 310 b.Error(opt.msg, bloom2, "to be part of", bloom1) 311 } 312 } 313 } 314 315 func Benchmark_Bloom_BitAND(b *testing.B) { 316 var bloom1 types.Bloom 317 for _, addr := range addrs { 318 bloom1.Add(new(big.Int).SetBytes([]byte(addr))) 319 } 320 321 for _, bm := range bitandBenchmarks { 322 b.Run(bm.name, func(b *testing.B) { 323 benchmark_Bloom_BitAND(b, bloom1, &bm.opt) 324 }) 325 } 326 } 327 328 func Benchmark_Bloom_BitAND_TrueNaive(b *testing.B) { 329 var bloom1 types.Bloom 330 var bloom2 types.Bloom 331 332 for _, addr := range addrs { 333 bloom1.Add(new(big.Int).SetBytes([]byte(addr))) 334 } 335 336 if len(addrs) > 0 { 337 bloom2.Add(new(big.Int).SetBytes([]byte(addrs[0]))) 338 } 339 340 bloomAnd := new(big.Int) 341 342 b.ResetTimer() 343 for k := 0; k < b.N; k++ { 344 bloom1Big := bloom1.Big() 345 bloom2Big := bloom2.Big() 346 if bloomAnd.And(bloom1Big, bloom2Big).Cmp(bloom2Big) != 0 { 347 b.Error("expected", bloom2Big, "to be part of", bloom1Big) 348 } 349 } 350 } 351 352 func Benchmark_LDBBloom_Add(b *testing.B) { 353 numAddrs := len(addrs) 354 355 b.ResetTimer() 356 for k := 0; k < b.N/numAddrs; k++ { 357 bloomFilter := filter.NewBloomFilter(bitsPerKey) 358 generator := bloomFilter.NewGenerator() 359 for _, addr := range addrs { 360 generator.Add([]byte(addr)) 361 } 362 buf := &util.Buffer{} 363 generator.Generate(buf) 364 } 365 } 366 367 func benchmark_LDBBloom_Lookup(b *testing.B, bloomFilter filter.Filter, filterInstance []byte, opt *testOption) { 368 numAddrs := len(opt.testAddrs) 369 370 b.ResetTimer() 371 for k := 0; k < b.N; k++ { 372 addr := opt.testAddrs[k%numAddrs] 373 if bloomFilter.Contains(filterInstance, []byte(addr)) != opt.expected { 374 b.Error(opt.msg, addr, "to test true") 375 } 376 } 377 } 378 379 func Benchmark_LDBBloom_Lookup(b *testing.B) { 380 bloomFilter := filter.NewBloomFilter(bitsPerKey) 381 generator := bloomFilter.NewGenerator() 382 for _, addr := range addrs { 383 generator.Add([]byte(addr)) 384 } 385 buf := &util.Buffer{} 386 generator.Generate(buf) 387 filterInstance := buf.Bytes() 388 389 for _, bm := range lookupBenchmarks { 390 b.Run(bm.name, func(b *testing.B) { 391 benchmark_LDBBloom_Lookup(b, bloomFilter, filterInstance, &bm.opt) 392 }) 393 } 394 } 395 396 func benchmark_LDBBloom_Compare(b *testing.B, bloomFilter filter.Filter, filterInstance1 []byte, opt *testOption) { 397 numAddrs := len(opt.testAddrs) 398 generator2 := bloomFilter.NewGenerator() 399 for i := 0; i < len(addrs); i++ { 400 generator2.Add([]byte(opt.testAddrs[i%numAddrs])) 401 } 402 buf2 := &util.Buffer{} 403 generator2.Generate(buf2) 404 filterInstance2 := buf2.Bytes() 405 406 b.ResetTimer() 407 for k := 0; k < b.N; k++ { 408 if bytes.Equal(filterInstance1, filterInstance2) != opt.expected { 409 b.Error("expected", filterInstance2, opt.msg, filterInstance1) 410 } 411 } 412 } 413 414 func Benchmark_LDBBloom_Compare(b *testing.B) { 415 bloomFilter := filter.NewBloomFilter(bitsPerKey) 416 417 generator1 := bloomFilter.NewGenerator() 418 for _, addr := range addrs { 419 generator1.Add([]byte(addr)) 420 } 421 buf1 := &util.Buffer{} 422 generator1.Generate(buf1) 423 filterInstance1 := buf1.Bytes() 424 425 for _, bm := range compareBenchmarks { 426 b.Run(bm.name, func(b *testing.B) { 427 benchmark_LDBBloom_Compare(b, bloomFilter, filterInstance1, &bm.opt) 428 }) 429 } 430 } 431 432 func benchmark_LDBBloom_BitAND(b *testing.B, bloomFilter filter.Filter, filterInstance1 []byte, opt *testOption) { 433 generator2 := bloomFilter.NewGenerator() 434 for i := 0; i < len(addrs); i++ { 435 generator2.Add([]byte(opt.testAddrs[0])) 436 } 437 buf2 := &util.Buffer{} 438 generator2.Generate(buf2) 439 filterInstance2 := buf2.Bytes() 440 441 b.ResetTimer() 442 for k := 0; k < b.N; k++ { 443 result := ldbBloomBitAND(filterInstance1, filterInstance2) 444 if bytes.Equal(result, filterInstance2) != opt.expected { 445 b.Error(opt.msg, filterInstance2, "to be part of", filterInstance1) 446 } 447 } 448 } 449 450 func Benchmark_LDBBloom_BitAND(b *testing.B) { 451 bloomFilter := filter.NewBloomFilter(bitsPerKey) 452 453 generator1 := bloomFilter.NewGenerator() 454 for _, addr := range addrs { 455 generator1.Add([]byte(addr)) 456 } 457 buf1 := &util.Buffer{} 458 generator1.Generate(buf1) 459 filterInstance1 := buf1.Bytes() 460 461 for _, bm := range bitandBenchmarks { 462 b.Run(bm.name, func(b *testing.B) { 463 benchmark_LDBBloom_BitAND(b, bloomFilter, filterInstance1, &bm.opt) 464 }) 465 } 466 }