Checking if an item should be promoted because it's new is the uncommon
case which we can optimize out by being more explicit when we create a new item
This commit is contained in:
parent
3fa767d9ff
commit
6720535fab
5 changed files with 25 additions and 17 deletions
|
@ -16,7 +16,7 @@ func (b *Bucket) get(key string) *Item {
|
|||
return b.lookup[key]
|
||||
}
|
||||
|
||||
func (b *Bucket) set(key string, value interface{}, duration time.Duration) *Item {
|
||||
func (b *Bucket) set(key string, value interface{}, duration time.Duration) (*Item, bool) {
|
||||
expires := time.Now().Add(duration)
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
@ -25,11 +25,11 @@ func (b *Bucket) set(key string, value interface{}, duration time.Duration) *Ite
|
|||
existing.value = value
|
||||
existing.expires = expires
|
||||
existing.Unlock()
|
||||
return existing
|
||||
return existing, false
|
||||
}
|
||||
item := newItem(key, value, expires)
|
||||
b.lookup[key] = item
|
||||
return item
|
||||
return item, true
|
||||
}
|
||||
|
||||
func (b *Bucket) delete(key string) {
|
||||
|
|
|
@ -3,7 +3,7 @@ package ccache
|
|||
import (
|
||||
"time"
|
||||
"testing"
|
||||
"github.com/karlseguin/gspec"
|
||||
"github.com/viki-org/gspec"
|
||||
)
|
||||
|
||||
func TestGetMissFromBucket(t *testing.T) {
|
||||
|
@ -24,19 +24,23 @@ func TestDeleteItemFromBucket(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSetsANewBucketItem(t *testing.T) {
|
||||
spec := gspec.New(t)
|
||||
bucket := testBucket()
|
||||
item := bucket.set("spice", TestValue("flow"), time.Minute)
|
||||
item, new := bucket.set("spice", TestValue("flow"), time.Minute)
|
||||
assertValue(t, item, "flow")
|
||||
item = bucket.get("spice")
|
||||
assertValue(t, item, "flow")
|
||||
spec.Expect(new).ToEqual(true)
|
||||
}
|
||||
|
||||
func TestSetsAnExistingItem(t *testing.T) {
|
||||
spec := gspec.New(t)
|
||||
bucket := testBucket()
|
||||
item := bucket.set("power", TestValue("9002"), time.Minute)
|
||||
item, new := bucket.set("power", TestValue("9002"), time.Minute)
|
||||
assertValue(t, item, "9002")
|
||||
item = bucket.get("power")
|
||||
assertValue(t, item, "9002")
|
||||
spec.Expect(new).ToEqual(false)
|
||||
}
|
||||
|
||||
func testBucket() *Bucket {
|
||||
|
|
16
cache.go
16
cache.go
|
@ -42,13 +42,17 @@ func (c *Cache) Get(key string) interface{} {
|
|||
c.deleteItem(bucket, item)
|
||||
return nil
|
||||
}
|
||||
c.promote(item)
|
||||
c.conditionalPromote(item)
|
||||
return item.value
|
||||
}
|
||||
|
||||
func (c *Cache) Set(key string, value interface{}, duration time.Duration) {
|
||||
item := c.bucket(key).set(key, value, duration)
|
||||
c.promote(item)
|
||||
item, new := c.bucket(key).set(key, value, duration)
|
||||
if new {
|
||||
c.promote(item)
|
||||
} else {
|
||||
c.conditionalPromote(item)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) Fetch(key string, duration time.Duration, fetch func() (interface{}, error)) (interface{}, error) {
|
||||
|
@ -88,8 +92,12 @@ func (c *Cache) bucket(key string) *Bucket {
|
|||
return c.buckets[index]
|
||||
}
|
||||
|
||||
func (c *Cache) promote(item *Item) {
|
||||
func (c *Cache) conditionalPromote(item *Item) {
|
||||
if item.shouldPromote(c.getsPerPromote) == false { return }
|
||||
c.promote(item)
|
||||
}
|
||||
|
||||
func (c *Cache) promote(item *Item) {
|
||||
c.promotables <- item
|
||||
}
|
||||
|
||||
|
|
2
item.go
2
item.go
|
@ -27,7 +27,7 @@ func newItem(key string, value interface{}, expires time.Time) *Item {
|
|||
|
||||
func (i *Item) shouldPromote(getsPerPromote int32) bool {
|
||||
promotions := atomic.AddInt32(&i.promotions, 1)
|
||||
if promotions == getsPerPromote || promotions == 0 {
|
||||
if promotions == getsPerPromote {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -2,16 +2,12 @@ package ccache
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"github.com/karlseguin/gspec"
|
||||
"github.com/viki-org/gspec"
|
||||
)
|
||||
|
||||
func TestItemPromotability(t *testing.T) {
|
||||
spec := gspec.New(t)
|
||||
item := &Item{promotions: -1}
|
||||
spec.Expect(item.shouldPromote(5)).ToEqual(true)
|
||||
spec.Expect(item.shouldPromote(5)).ToEqual(false)
|
||||
|
||||
item.promotions = 4
|
||||
item := &Item{promotions: 4}
|
||||
spec.Expect(item.shouldPromote(5)).ToEqual(true)
|
||||
spec.Expect(item.shouldPromote(5)).ToEqual(false)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue