mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-07 17:15:56 +00:00
cache performance enhancement
This commit is contained in:
parent
283dfef1d9
commit
cabe0fef24
3 changed files with 75 additions and 17 deletions
23
bitmap.go
23
bitmap.go
|
|
@ -16,6 +16,8 @@ type Bitmap struct {
|
|||
|
||||
// Attributes associated with the bitmap.
|
||||
Attrs map[string]interface{}
|
||||
|
||||
cacheoveride uint64
|
||||
}
|
||||
|
||||
// NewBitmap returns a new instance of Bitmap.
|
||||
|
|
@ -174,6 +176,26 @@ func (b *Bitmap) InvalidateCount() {
|
|||
}
|
||||
}
|
||||
|
||||
//increment the bitmap cached counter, note this is an optimization that assumes that the caller is aware the size increased
|
||||
func (b *Bitmap) IncrementCount(i uint64) {
|
||||
seg := b.segment(i / SliceWidth)
|
||||
if seg != nil {
|
||||
seg.n++
|
||||
}
|
||||
}
|
||||
func (b *Bitmap) DecrementCount(i uint64) {
|
||||
seg := b.segment(i / SliceWidth)
|
||||
if seg != nil {
|
||||
if seg.n > 0 {
|
||||
seg.n--
|
||||
}
|
||||
}
|
||||
}
|
||||
func (b *Bitmap) SetCount(i uint64, count uint64) {
|
||||
seg := b.segment(i / SliceWidth)
|
||||
seg.n = count
|
||||
}
|
||||
|
||||
// Count returns the number of set bits in the bitmap.
|
||||
func (b *Bitmap) Count() uint64 {
|
||||
var n uint64
|
||||
|
|
@ -312,7 +334,6 @@ func (s *BitmapSegment) Difference(other *BitmapSegment) *BitmapSegment {
|
|||
// SetBit sets the i-th bit of the bitmap.
|
||||
func (s *BitmapSegment) SetBit(i uint64) (changed bool) {
|
||||
s.ensureWritable()
|
||||
|
||||
changed, _ = s.data.Add(i)
|
||||
if changed {
|
||||
s.n++
|
||||
|
|
|
|||
47
cache.go
47
cache.go
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/groupcache/lru"
|
||||
|
|
@ -97,6 +98,7 @@ var _ Cache = &LRUCache{}
|
|||
|
||||
// RankCache represents a cache with sorted entries.
|
||||
type RankCache struct {
|
||||
mu sync.Mutex
|
||||
entries map[uint64]uint64
|
||||
rankings []BitmapPair // cached, ordered list
|
||||
|
||||
|
|
@ -117,6 +119,8 @@ func NewRankCache() *RankCache {
|
|||
|
||||
// Add adds a bitmap to the cache.
|
||||
func (c *RankCache) Add(bitmapID uint64, n uint64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
// Ignore if the bit count on the bitmap is below the threshold.
|
||||
if n < c.ThresholdValue {
|
||||
return
|
||||
|
|
@ -124,19 +128,13 @@ func (c *RankCache) Add(bitmapID uint64, n uint64) {
|
|||
|
||||
c.entries[bitmapID] = n
|
||||
|
||||
c.Invalidate()
|
||||
// If size is larger than the threshold then trim it.
|
||||
if len(c.entries) > c.ThresholdLength {
|
||||
for id, n := range c.entries {
|
||||
if n <= c.ThresholdValue {
|
||||
delete(c.entries, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
c.invalidate()
|
||||
}
|
||||
|
||||
// BulkAdd adds a bitmap to the cache unsorted. You should Invalidate after completion.
|
||||
func (c *RankCache) BulkAdd(bitmapID uint64, n uint64) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if n < c.ThresholdValue {
|
||||
return
|
||||
}
|
||||
|
|
@ -145,13 +143,23 @@ func (c *RankCache) BulkAdd(bitmapID uint64, n uint64) {
|
|||
}
|
||||
|
||||
// Get returns a bitmap with a given id.
|
||||
func (c *RankCache) Get(bitmapID uint64) uint64 { return c.entries[bitmapID] }
|
||||
func (c *RankCache) Get(bitmapID uint64) uint64 {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.entries[bitmapID]
|
||||
}
|
||||
|
||||
// Len returns the number of items in the cache.
|
||||
func (c *RankCache) Len() int { return len(c.entries) }
|
||||
func (c *RankCache) Len() int {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return len(c.entries)
|
||||
}
|
||||
|
||||
// BitmapIDs returns a list of all bitmap IDs in the cache.
|
||||
func (c *RankCache) BitmapIDs() []uint64 {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
a := make([]uint64, 0, len(c.entries))
|
||||
for id := range c.entries {
|
||||
a = append(a, id)
|
||||
|
|
@ -162,6 +170,15 @@ func (c *RankCache) BitmapIDs() []uint64 {
|
|||
|
||||
// update reorders the entries by rank.
|
||||
func (c *RankCache) Invalidate() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.invalidate()
|
||||
|
||||
}
|
||||
func (c *RankCache) invalidate() {
|
||||
if time.Now().Sub(c.updateTime).Seconds() < 10 {
|
||||
return
|
||||
}
|
||||
//fmt.Println("RankCache Update")
|
||||
// Convert cache to a sorted list.
|
||||
rankings := make([]BitmapPair, 0, len(c.entries))
|
||||
|
|
@ -183,6 +200,14 @@ func (c *RankCache) Invalidate() {
|
|||
|
||||
// Reset counters.
|
||||
c.updateTime, c.updateN = time.Now(), 0
|
||||
// If size is larger than the threshold then trim it.
|
||||
if len(c.entries) > c.ThresholdLength {
|
||||
for id, n := range c.entries {
|
||||
if n <= c.ThresholdValue {
|
||||
delete(c.entries, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Top returns an ordered list of bitmaps.
|
||||
|
|
|
|||
22
fragment.go
22
fragment.go
|
|
@ -351,8 +351,10 @@ func (f *Fragment) bitmap(bitmapID uint64, updateCache bool) *Bitmap {
|
|||
slice: f.slice,
|
||||
writable: false,
|
||||
}},
|
||||
cacheoveride: 0,
|
||||
}
|
||||
bm.InvalidateCount()
|
||||
bm.cacheoveride = bm.Count()
|
||||
|
||||
if updateCache {
|
||||
// Update cache.
|
||||
|
|
@ -380,6 +382,7 @@ func (f *Fragment) setBit(bitmapID, profileID uint64) (changed bool, bool error)
|
|||
}
|
||||
|
||||
// Write to storage.
|
||||
|
||||
if changed, err = f.storage.Add(pos); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
@ -399,8 +402,13 @@ func (f *Fragment) setBit(bitmapID, profileID uint64) (changed bool, bool error)
|
|||
|
||||
// Update the cache.
|
||||
bm := f.bitmap(bitmapID, true)
|
||||
bm.SetBit(profileID)
|
||||
bm.InvalidateCount() //maybe a perf opportunity?
|
||||
if bm.cacheoveride > 0 {
|
||||
bm.SetCount(profileID, bm.cacheoveride)
|
||||
bm.cacheoveride = 0
|
||||
} else {
|
||||
bm.IncrementCount(profileID)
|
||||
}
|
||||
|
||||
f.cache.Add(bitmapID, bm.Count())
|
||||
|
||||
f.stats.Count("setN", 1)
|
||||
|
|
@ -443,9 +451,13 @@ func (f *Fragment) clearBit(bitmapID, profileID uint64) (bool, error) {
|
|||
}
|
||||
|
||||
// Update the cache.
|
||||
bm := f.bitmap(bitmapID, true)
|
||||
bm.ClearBit(profileID)
|
||||
bm.InvalidateCount() //maybe a perf opportunity?
|
||||
bm := f.bitmap(bitmapID, false)
|
||||
if bm.cacheoveride > 0 {
|
||||
bm.SetCount(profileID, bm.cacheoveride)
|
||||
bm.cacheoveride = 0
|
||||
} else {
|
||||
bm.DecrementCount(profileID)
|
||||
}
|
||||
f.cache.Add(bitmapID, bm.Count())
|
||||
|
||||
f.stats.Count("clearN", 1)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue