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  }