Skip to content

Commit f90a0b9

Browse files
committed
improve performance
1 parent 25621a5 commit f90a0b9

File tree

4 files changed

+33
-24
lines changed

4 files changed

+33
-24
lines changed

cuckoofilter.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import (
44
"bytes"
55
"encoding/binary"
66
"fmt"
7-
"math/rand"
7+
8+
"github.com/zeebo/wyhash"
89
)
910

1011
// maxCuckooKickouts is the maximum number of times reinsert
@@ -18,6 +19,7 @@ type Filter struct {
1819
// Bit mask set to len(buckets) - 1. As len(buckets) is always a power of 2,
1920
// applying this mask mimics the operation x % len(buckets).
2021
bucketIndexMask uint
22+
rng wyhash.RNG
2123
}
2224

2325
// NewFilter returns a new cuckoofilter suitable for the given number of elements.
@@ -72,7 +74,7 @@ func (cf *Filter) Insert(data []byte) bool {
7274
if cf.insert(fp, i2) {
7375
return true
7476
}
75-
return cf.reinsert(fp, randi(i1, i2))
77+
return cf.reinsert(fp, randi(&cf.rng, i1, i2))
7678
}
7779

7880
func (cf *Filter) insert(fp fingerprint, i uint) bool {
@@ -85,7 +87,7 @@ func (cf *Filter) insert(fp fingerprint, i uint) bool {
8587

8688
func (cf *Filter) reinsert(fp fingerprint, i uint) bool {
8789
for k := 0; k < maxCuckooKickouts; k++ {
88-
j := rand.Intn(bucketSize)
90+
j := cf.rng.Intn(bucketSize)
8991
// Swap fingerprint with bucket entry.
9092
cf.buckets[i][j], fp = fp, cf.buckets[i][j]
9193

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/panmari/cuckoofilter
33
go 1.15
44

55
require (
6-
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165
76
github.com/google/go-cmp v0.5.9
7+
github.com/zeebo/wyhash v0.0.1
8+
github.com/zeebo/xxh3 v1.0.2
89
)

go.sum

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E=
2-
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
31
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
42
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
3+
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
4+
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
5+
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
6+
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
7+
github.com/zeebo/wyhash v0.0.1 h1:VEByEMek3iHhV65CgG3SRAWVtg/6TcmbEKj5jPOKDrc=
8+
github.com/zeebo/wyhash v0.0.1/go.mod h1:Ti+OwfNtM5AZiYAL0kOPIfliqDP5c0VtOnnMAqzuuZk=
9+
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
10+
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=

util.go

+18-18
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,32 @@ package cuckoo
22

33
import (
44
"encoding/binary"
5-
"math/rand"
5+
"math/bits"
66

7-
metro "github.com/dgryski/go-metro"
7+
"github.com/zeebo/wyhash"
8+
"github.com/zeebo/xxh3"
89
)
910

11+
var altHash [maxFingerprint + 1]uint
12+
13+
func init() {
14+
b := make([]byte, 2)
15+
for i := 0; i < maxFingerprint+1; i++ {
16+
binary.LittleEndian.PutUint16(b, uint16(i))
17+
altHash[i] = (uint(xxh3.Hash(b)))
18+
}
19+
}
20+
1021
// randi returns either i1 or i2 randomly.
11-
func randi(i1, i2 uint) uint {
12-
if rand.Int31()%2 == 0 {
22+
func randi(rng *wyhash.RNG, i1, i2 uint) uint {
23+
if rng.Uint64()&1 == 0 {
1324
return i1
1425
}
1526
return i2
1627
}
1728

1829
func getAltIndex(fp fingerprint, i uint, bucketIndexMask uint) uint {
19-
b := make([]byte, 2)
20-
binary.LittleEndian.PutUint16(b, uint16(fp))
21-
hash := uint(metro.Hash64(b, 1337))
22-
return (i ^ hash) & bucketIndexMask
30+
return (i ^ altHash[fp]) & bucketIndexMask
2331
}
2432

2533
func getFingerprint(hash uint64) fingerprint {
@@ -32,21 +40,13 @@ func getFingerprint(hash uint64) fingerprint {
3240

3341
// getIndexAndFingerprint returns the primary bucket index and fingerprint to be used
3442
func getIndexAndFingerprint(data []byte, bucketIndexMask uint) (uint, fingerprint) {
35-
hash := metro.Hash64(data, 1337)
43+
hash := xxh3.Hash(data)
3644
f := getFingerprint(hash)
3745
// Use least significant bits for deriving index.
3846
i1 := uint(hash) & bucketIndexMask
3947
return i1, f
4048
}
4149

4250
func getNextPow2(n uint64) uint {
43-
n--
44-
n |= n >> 1
45-
n |= n >> 2
46-
n |= n >> 4
47-
n |= n >> 8
48-
n |= n >> 16
49-
n |= n >> 32
50-
n++
51-
return uint(n)
51+
return uint(1 << bits.Len64(n-1))
5252
}

0 commit comments

Comments
 (0)