Skip to content

Commit

Permalink
Add Cache.Has method
Browse files Browse the repository at this point in the history
  • Loading branch information
valyala committed May 2, 2019
1 parent 937beb6 commit 46cbf15
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
19 changes: 15 additions & 4 deletions fastcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,16 @@ func (c *Cache) Set(k, v []byte) {
func (c *Cache) Get(dst, k []byte) []byte {
h := xxhash.Sum64(k)
idx := h % bucketsCount
return c.buckets[idx].Get(dst, k, h)
dst, _ = c.buckets[idx].Get(dst, k, h, true)
return dst
}

// Has returns true if entry for the given key k exists in the cache.
func (c *Cache) Has(k []byte) bool {
h := xxhash.Sum64(k)
idx := h % bucketsCount
_, ok := c.buckets[idx].Get(nil, k, h, false)
return ok
}

// Del deletes value for the given k from the cache.
Expand Down Expand Up @@ -332,7 +341,7 @@ func (b *bucket) Set(k, v []byte, h uint64) {
b.mu.Unlock()
}

func (b *bucket) Get(dst, k []byte, h uint64) []byte {
func (b *bucket) Get(dst, k []byte, h uint64, returnDst bool) ([]byte, bool) {
atomic.AddUint64(&b.getCalls, 1)
found := false
b.mu.RLock()
Expand Down Expand Up @@ -365,7 +374,9 @@ func (b *bucket) Get(dst, k []byte, h uint64) []byte {
}
if string(k) == string(chunk[idx:idx+keyLen]) {
idx += keyLen
dst = append(dst, chunk[idx:idx+valLen]...)
if returnDst {
dst = append(dst, chunk[idx:idx+valLen]...)
}
found = true
} else {
atomic.AddUint64(&b.collisions, 1)
Expand All @@ -377,7 +388,7 @@ end:
if !found {
atomic.AddUint64(&b.misses, 1)
}
return dst
return dst, found
}

func (b *bucket) Del(h uint64) {
Expand Down
14 changes: 14 additions & 0 deletions fastcache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,20 @@ func TestCacheSmall(t *testing.T) {
if len(v) != 0 {
t.Fatalf("unexpected non-empty value obtained from empty cache: %q", v)
}

// Test empty value
k := []byte("empty")
c.Set(k, nil)
v = c.Get(nil, k)
if len(v) != 0 {
t.Fatalf("unexpected non-empty value obtained from empty entry: %q", v)
}
if !c.Has(k) {
t.Fatalf("cannot find empty entry for key %q", k)
}
if c.Has([]byte("foobar")) {
t.Fatalf("non-existing entry found in the cache")
}
}

func TestCacheWrap(t *testing.T) {
Expand Down
31 changes: 31 additions & 0 deletions fastcache_timing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,37 @@ func BenchmarkCacheGet(b *testing.B) {
})
}

func BenchmarkCacheHas(b *testing.B) {
const items = 1 << 16
c := New(12 * items)
defer c.Reset()
k := []byte("\x00\x00\x00\x00")
for i := 0; i < items; i++ {
k[0]++
if k[0] == 0 {
k[1]++
}
c.Set(k, nil)
}

b.ReportAllocs()
b.SetBytes(items)
b.RunParallel(func(pb *testing.PB) {
k := []byte("\x00\x00\x00\x00")
for pb.Next() {
for i := 0; i < items; i++ {
k[0]++
if k[0] == 0 {
k[1]++
}
if !c.Has(k) {
panic(fmt.Errorf("BUG: missing value for key %q", k))
}
}
}
})
}

func BenchmarkCacheSetGet(b *testing.B) {
const items = 1 << 16
c := New(12 * items)
Expand Down

0 comments on commit 46cbf15

Please sign in to comment.