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 }