Skip to content

Commit

Permalink
switch to maphash from wyhash
Browse files Browse the repository at this point in the history
  • Loading branch information
phuslu committed Jan 2, 2024
1 parent c178f0d commit fefd6a9
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 189 deletions.
46 changes: 11 additions & 35 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ package lru
import (
"runtime"
"time"
"unsafe"
)

// Cache implements LRU Cache with least recent used eviction policy.
type Cache[K comparable, V any] struct {
shards []shard[K, V]
mask uint32
keysize int
shards []shard[K, V]
mask uint32
hasher maphash_Hasher[K]
}

// New creates lru cache with size capacity.
Expand All @@ -31,65 +30,42 @@ func newWithShards[K comparable, V any](shardcount, shardsize int) *Cache[K, V]
c := &Cache[K, V]{
shards: make([]shard[K, V], shardcount),
mask: uint32(shardcount) - 1,
hasher: maphash_NewHasher[K](),
}
for i := range c.shards {
c.shards[i] = *newshard[K, V](shardsize)
}

var k K
switch ((any)(k)).(type) {
case string:
c.keysize = 0
default:
c.keysize = int(unsafe.Sizeof(k))
}

return c
}

func (c *Cache[K, V]) hash(key K) uint32 {
if c.keysize == 0 {
data := *(*string)(unsafe.Pointer(&key))
if len(data) == 0 {
return 0
}

return uint32(wyhash_hash(data, 0) & 0xFFFFFFFF)
}

return uint32(wyhash_hash(*(*string)(unsafe.Pointer(&struct {
data unsafe.Pointer
len int
}{unsafe.Pointer(&key), c.keysize})), 0) & 0xFFFFFFFF)
}

// Get returns value for key.
func (c *Cache[K, V]) Get(key K) (value V, ok bool) {
hash := c.hash(key)
hash := uint32(c.hasher.Hash(key) & 0xFFFFFFFF)
return c.shards[hash&c.mask].Get(hash, key)
}

// Peek returns value for key, but does not modify its recency.
func (c *Cache[K, V]) Peek(key K) (value V, ok bool) {
hash := c.hash(key)
hash := uint32(c.hasher.Hash(key) & 0xFFFFFFFF)
return c.shards[hash&c.mask].Peek(hash, key)
}

// Set inserts key value pair and returns previous value, if cache was full.
func (c *Cache[K, V]) Set(key K, value V) (prev V, replaced bool) {
hash := c.hash(key)
return c.shards[hash&c.mask].Set(hash, c.hash, key, value, 0)
hash := uint32(c.hasher.Hash(key) & 0xFFFFFFFF)
return c.shards[hash&c.mask].Set(hash, c.hasher.Hash, key, value, 0)
}

// SetWithTTL inserts key value pair with ttl and returns previous value, if cache was full.
func (c *Cache[K, V]) SetWithTTL(key K, value V, ttl time.Duration) (prev V, replaced bool) {
hash := c.hash(key)
return c.shards[hash&c.mask].Set(hash, c.hash, key, value, ttl)
hash := uint32(c.hasher.Hash(key) & 0xFFFFFFFF)
return c.shards[hash&c.mask].Set(hash, c.hasher.Hash, key, value, ttl)
}

// Delete method deletes value associated with key and returns deleted value (or empty value if key was not in cache).
func (c *Cache[K, V]) Delete(key K) (prev V) {
hash := c.hash(key)
hash := uint32(c.hasher.Hash(key) & 0xFFFFFFFF)
return c.shards[hash&c.mask].Delete(hash, key)
}

Expand Down
137 changes: 137 additions & 0 deletions maphash.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions shard.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (s *shard[K, V]) Peek(hash uint32, key K) (value V, ok bool) {
return
}

func (s *shard[K, V]) Set(hash uint32, hashfun func(K) uint32, key K, value V, ttl time.Duration) (prev V, replaced bool) {
func (s *shard[K, V]) Set(hash uint32, hashfun func(K) uint64, key K, value V, ttl time.Duration) (prev V, replaced bool) {
s.mu.Lock()
defer s.mu.Unlock()

Expand All @@ -72,7 +72,7 @@ func (s *shard[K, V]) Set(hash uint32, hashfun func(K) uint32, key K, value V, t
index := s.list.Back()
node := &s.list.nodes[index]
evictedValue := node.value
s.table.Delete(hashfun(node.key), node.key)
s.table.Delete(uint32(hashfun(node.key)&0xFFFFFFFF), node.key)

node.key = key
node.value = value
Expand Down
Loading

0 comments on commit fefd6a9

Please sign in to comment.