diff --git a/go.mod b/go.mod index f261456..2008524 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/panmari/cuckoofilter go 1.15 require ( - github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 - github.com/google/go-cmp v0.5.9 -) + github.com/google/go-cmp v0.5.9 + github.com/zeebo/wyhash v0.0.2-0.20221101160656-7c89dcff99fa + github.com/zeebo/xxh3 v1.0.2 +) \ No newline at end of file diff --git a/go.sum b/go.sum index aabbb23..a62ea45 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,10 @@ -github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E= -github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/wyhash v0.0.2-0.20221101160656-7c89dcff99fa h1:icNAX4PdeSmRwz4fmsMSUmYSPz+agsgrEe67BFrLFBM= +github.com/zeebo/wyhash v0.0.2-0.20221101160656-7c89dcff99fa/go.mod h1:Ti+OwfNtM5AZiYAL0kOPIfliqDP5c0VtOnnMAqzuuZk= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= diff --git a/util.go b/util.go index 00f6309..1fc82cc 100644 --- a/util.go +++ b/util.go @@ -2,24 +2,46 @@ package cuckoo import ( "encoding/binary" - "math/rand" + "unsafe" - metro "github.com/dgryski/go-metro" + "github.com/zeebo/wyhash" + "github.com/zeebo/xxh3" +) + +var ( + // plus 1 to prevent out of range. + altHash = [maxFingerprint + 1]uint{} + rng wyhash.SRNG ) // randi returns either i1 or i2 randomly. func randi(i1, i2 uint) uint { - if rand.Int31()%2 == 0 { + // it's faster than mod, but the result is the almost same. + if uint32(uint64(uint32(rng.Uint64()))*uint64(2)>>32) == 0 { return i1 } return i2 } +func getEndian() (endian binary.ByteOrder) { + var i int = 0x1 + bs := (*[int(unsafe.Sizeof(0))]byte)(unsafe.Pointer(&i)) + if bs[0] == 0 { + return binary.BigEndian + } else { + return binary.LittleEndian + } +} +func init() { + b := make([]byte, 2) + endian := getEndian() + for i := 0; i < maxFingerprint+1; i++ { + endian.PutUint16(b, uint16(i)) + altHash[i] = (uint(xxh3.Hash(b))) + } +} func getAltIndex(fp fingerprint, i uint, bucketIndexMask uint) uint { - b := make([]byte, 2) - binary.LittleEndian.PutUint16(b, uint16(fp)) - hash := uint(metro.Hash64(b, 1337)) - return (i ^ hash) & bucketIndexMask + return (i ^ altHash[fp]) & bucketIndexMask } func getFingerprint(hash uint64) fingerprint { @@ -32,7 +54,7 @@ func getFingerprint(hash uint64) fingerprint { // getIndexAndFingerprint returns the primary bucket index and fingerprint to be used func getIndexAndFingerprint(data []byte, bucketIndexMask uint) (uint, fingerprint) { - hash := metro.Hash64(data, 1337) + hash := xxh3.Hash(data) f := getFingerprint(hash) // Use least significant bits for deriving index. i1 := uint(hash) & bucketIndexMask