Skip to content

Commit

Permalink
Including access time of deleted entries when calculating average ace…
Browse files Browse the repository at this point in the history
…ss time, improves cache hit rate.
  • Loading branch information
coocood committed May 6, 2015
1 parent 2b0bf4c commit 87ca74b
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 17 deletions.
2 changes: 1 addition & 1 deletion cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (cache *Cache) AverageAccessTime() int64 {
var entryCount, totalTime int64
for i := 0; i < 256; i++ {
totalTime += atomic.LoadInt64(&cache.segments[i].totalTime)
entryCount += atomic.LoadInt64(&cache.segments[i].entryCount)
entryCount += atomic.LoadInt64(&cache.segments[i].totalCount)
}
if entryCount == 0 {
return 0
Expand Down
5 changes: 2 additions & 3 deletions ringbuf_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package freecache

import (
"fmt"
"testing"
)

Expand All @@ -11,13 +10,13 @@ func TestRingBuf(t *testing.T) {
rb.Write([]byte("fghibbbbc"))
rb.Resize(16)
off := rb.Evacuate(9, 3)
fmt.Println(string(rb.Dump()))
t.Log(string(rb.Dump()))
if off != rb.End()-3 {
t.Log(string(rb.Dump()), rb.End())
t.Fatalf("off got %v", off)
}
off = rb.Evacuate(15, 5)
fmt.Println(string(rb.Dump()))
t.Log(string(rb.Dump()))
if off != rb.End()-5 {
t.Fatalf("off got %v", off)
}
Expand Down
24 changes: 11 additions & 13 deletions segment.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type segment struct {
rb RingBuf // ring buffer that stores data
segId int
entryCount int64
totalCount int64 // number of entries including deleted entries.
totalTime int64 // used to calculate least recent used entry.
totalEvacuate int64 // used for debug
vacuumLen int64 // up to vacuumLen, new data can be written without overwriting old data.
Expand Down Expand Up @@ -89,14 +90,18 @@ func (seg *segment) set(key, value []byte, hashVal uint64, expireSeconds int) (e
oldEntryLen := int64(oldHdr.keyLen) + int64(oldHdr.valLen) + ENTRY_HDR_SIZE
if oldHdr.deleted {
consecutiveEvacuate = 0
seg.totalTime -= int64(oldHdr.accessTime)
seg.totalCount--
seg.vacuumLen += oldEntryLen
continue
}
expired := oldHdr.expireAt != 0 && oldHdr.expireAt < now
leastRecentUsed := int64(oldHdr.accessTime)*seg.entryCount <= seg.totalTime
leastRecentUsed := int64(oldHdr.accessTime)*seg.totalCount <= seg.totalTime
if expired || leastRecentUsed || consecutiveEvacuate > 5 {
seg.delEntryPtr(oldHdr.slotId, oldHdr.hash16, oldOff)
consecutiveEvacuate = 0
seg.totalTime -= int64(oldHdr.accessTime)
seg.totalCount--
seg.vacuumLen += oldEntryLen
} else {
// evacuate an old entry that has been accessed recently for better cache hit rate.
Expand All @@ -111,8 +116,10 @@ func (seg *segment) set(key, value []byte, hashVal uint64, expireSeconds int) (e
seg.rb.Write(hdrBuf[:])
seg.rb.Write(key)
seg.rb.Write(value)
seg.totalTime += int64(now)
seg.totalCount++
seg.vacuumLen -= entryLen
seg.setEntryPtr(key, off, hdr.hash16, hdr.slotId, now)
seg.setEntryPtr(key, off, hdr.hash16, hdr.slotId)
return
}

Expand Down Expand Up @@ -204,14 +211,11 @@ func (seg *segment) updateEntryPtr(oldOff, newOff int64, hash16 uint16, slotId u
return
}
idx++
if idx == len(slot) {
break
}
ptr = &slot[idx]
}
}

func (seg *segment) setEntryPtr(key []byte, offset int64, hash16 uint16, slotId uint8, accessTime uint32) {
func (seg *segment) setEntryPtr(key []byte, offset int64, hash16 uint16, slotId uint8) {
var ptr entryPtr
ptr.offset = offset
ptr.hash16 = hash16
Expand All @@ -232,7 +236,6 @@ func (seg *segment) setEntryPtr(key []byte, offset int64, hash16 uint16, slotId
oldEntryHdr := (*entryHdr)(unsafe.Pointer(&oldEntryHdrBuf[0]))
oldEntryHdr.deleted = true
seg.rb.WriteAt(oldEntryHdrBuf[:], oldPtr.offset)
seg.totalTime += int64(accessTime - oldEntryHdr.accessTime)
// update entry pointer
oldPtr.offset = offset
return
Expand All @@ -245,11 +248,10 @@ func (seg *segment) setEntryPtr(key []byte, offset int64, hash16 uint16, slotId
slotOff *= 2
}
seg.slotLens[slotId]++
seg.entryCount++
slot = seg.slotsData[slotOff : slotOff+seg.slotLens[slotId] : slotOff+seg.slotCap]
copy(slot[idx+1:], slot[idx:])
slot[idx] = ptr
seg.entryCount++
seg.totalTime += int64(accessTime)
}

func (seg *segment) delEntryPtr(slotId uint8, hash16 uint16, offset int64) {
Expand All @@ -267,13 +269,9 @@ func (seg *segment) delEntryPtr(slotId uint8, hash16 uint16, offset int64) {
copy(slot[idx:], slot[idx+1:])
seg.slotLens[slotId]--
seg.entryCount--
seg.totalTime -= int64(entryHdr.accessTime)
return
}
idx++
if idx == len(slot) {
break
}
ptr = &slot[idx]
}
}
Expand Down

0 comments on commit 87ca74b

Please sign in to comment.