use integer counter for promotions instead of time

This commit is contained in:
Karl Seguin 2013-10-21 19:37:35 +08:00
parent 7a8102e166
commit 36e5fae491
5 changed files with 28 additions and 25 deletions

View file

@ -24,7 +24,7 @@ func (b *Bucket) set(key string, value Value) *Item {
existing.Unlock() existing.Unlock()
return existing return existing
} }
item := &Item{key: key, value: value} item := newItem(key, value)
b.lookup[key] = item b.lookup[key] = item
return item return item
} }

View file

@ -56,7 +56,7 @@ func (c *Cache) bucket(key string) *Bucket {
} }
func (c *Cache) promote(item *Item) { func (c *Cache) promote(item *Item) {
if item.shouldPromote(c.promoteDelay) == false { return } if item.shouldPromote() == false { return }
c.promotables <- item c.promotables <- item
} }
@ -75,7 +75,7 @@ func (c *Cache) worker() {
func (c *Cache) doPromote(item *Item) bool { func (c *Cache) doPromote(item *Item) bool {
item.Lock() item.Lock()
defer item.Unlock() defer item.Unlock()
item.promoted = time.Now() item.promotions = 0
if item.element != nil { //not a new item if item.element != nil { //not a new item
c.list.MoveToFront(item.element) c.list.MoveToFront(item.element)
return false return false

View file

@ -1,15 +1,10 @@
package ccache package ccache
import (
"time"
)
type Configuration struct { type Configuration struct {
size uint64 size uint64
buckets int buckets int
itemsToPrune int itemsToPrune int
promoteBuffer int promoteBuffer int
promoteDelay time.Duration
} }
func Configure() *Configuration { func Configure() *Configuration {
@ -18,7 +13,6 @@ func Configure() *Configuration {
itemsToPrune: 500, itemsToPrune: 500,
promoteBuffer: 1024, promoteBuffer: 1024,
size: 500 * 1024 * 1024, size: 500 * 1024 * 1024,
promoteDelay: time.Minute * -5,
} }
} }
@ -41,8 +35,3 @@ func (c *Configuration) PromoteBuffer(size int) *Configuration {
c.promoteBuffer = size c.promoteBuffer = size
return c return c
} }
func (c *Configuration) PromoteDelay(delay time.Duration) *Configuration {
c.promoteDelay = -delay
return c
}

25
item.go
View file

@ -2,21 +2,32 @@ package ccache
import ( import (
"sync" "sync"
"time" "sync/atomic"
"container/list" "container/list"
) )
const promoteCap = 5
type Item struct { type Item struct {
key string key string
value Value value Value
sync.RWMutex sync.RWMutex
promoted time.Time promotions int32
element *list.Element element *list.Element
} }
func (i *Item) shouldPromote(staleness time.Duration) bool { func newItem(key string, value Value) *Item {
stale := time.Now().Add(staleness) return &Item{
i.RLock() key: key,
defer i.RUnlock() value: value,
return i.promoted.Before(stale) promotions: -1,
}
}
func (i *Item) shouldPromote() bool {
promotions := atomic.AddInt32(&i.promotions, 1)
if promotions == promoteCap || promotions == 0 {
return true
}
return false
} }

View file

@ -1,14 +1,17 @@
package ccache package ccache
import ( import (
"time"
"testing" "testing"
"github.com/karlseguin/gspec" "github.com/karlseguin/gspec"
) )
func TestItemPromotability(t *testing.T) { func TestItemPromotability(t *testing.T) {
spec := gspec.New(t) spec := gspec.New(t)
item := &Item{promoted: time.Now().Add(time.Second * -5)} item := &Item{promotions: -1}
spec.Expect(item.shouldPromote(time.Second * -2)).ToEqual(true) spec.Expect(item.shouldPromote()).ToEqual(true)
spec.Expect(item.shouldPromote(time.Second * -6)).ToEqual(false) spec.Expect(item.shouldPromote()).ToEqual(false)
item.promotions = 4
spec.Expect(item.shouldPromote()).ToEqual(true)
spec.Expect(item.shouldPromote()).ToEqual(false)
} }