github.com/parquet-go/parquet-go@v0.21.1-0.20240501160520-b3c3a0c3ed6f/bloom/block_optimized.go (about)

     1  //go:build (!amd64 || purego) && !parquet.bloom.no_unroll
     2  
     3  package bloom
     4  
     5  // The functions in this file are optimized versions of the algorithms described
     6  // in https://github.com/apache/parquet-format/blob/master/BloomFilter.md
     7  //
     8  // The functions are manual unrolling of the loops, which yield significant
     9  // performance improvements:
    10  //
    11  // goos: darwin
    12  // goarch: amd64
    13  // pkg: github.com/parquet-go/parquet-go/bloom
    14  // cpu: Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
    15  //
    16  // name         old time/op    new time/op      delta
    17  // BlockInsert     327ns ± 1%        12ns ± 4%    -96.47%  (p=0.000 n=9+8)
    18  // BlockCheck      240ns ± 4%        13ns ±28%    -94.75%  (p=0.000 n=8+10)
    19  //
    20  // name         old speed      new speed        delta
    21  // BlockInsert  97.8MB/s ± 1%  2725.0MB/s ±13%  +2686.59%  (p=0.000 n=9+9)
    22  // BlockCheck    133MB/s ± 4%    2587MB/s ±23%  +1838.46%  (p=0.000 n=8+10)
    23  //
    24  // The benchmarks measure throughput based on the byte size of a bloom filter
    25  // block.
    26  
    27  func (b *Block) Insert(x uint32) {
    28  	b[0] |= 1 << ((x * salt0) >> 27)
    29  	b[1] |= 1 << ((x * salt1) >> 27)
    30  	b[2] |= 1 << ((x * salt2) >> 27)
    31  	b[3] |= 1 << ((x * salt3) >> 27)
    32  	b[4] |= 1 << ((x * salt4) >> 27)
    33  	b[5] |= 1 << ((x * salt5) >> 27)
    34  	b[6] |= 1 << ((x * salt6) >> 27)
    35  	b[7] |= 1 << ((x * salt7) >> 27)
    36  }
    37  
    38  func (b *Block) Check(x uint32) bool {
    39  	return ((b[0] & (1 << ((x * salt0) >> 27))) != 0) &&
    40  		((b[1] & (1 << ((x * salt1) >> 27))) != 0) &&
    41  		((b[2] & (1 << ((x * salt2) >> 27))) != 0) &&
    42  		((b[3] & (1 << ((x * salt3) >> 27))) != 0) &&
    43  		((b[4] & (1 << ((x * salt4) >> 27))) != 0) &&
    44  		((b[5] & (1 << ((x * salt5) >> 27))) != 0) &&
    45  		((b[6] & (1 << ((x * salt6) >> 27))) != 0) &&
    46  		((b[7] & (1 << ((x * salt7) >> 27))) != 0)
    47  }
    48  
    49  func (f SplitBlockFilter) insertBulk(x []uint64) {
    50  	for i := range x {
    51  		f.Insert(x[i])
    52  	}
    53  }