@@ -34,7 +34,7 @@ func NewShardedLRURevisionCache(revCacheOptions *RevisionCacheOptions, backingSt
34
34
revCacheOptions .MaxItemCount = uint32 (perCacheCapacity )
35
35
var perCacheMemoryCapacity float32
36
36
if revCacheOptions .MaxBytes > 0 {
37
- perCacheMemoryCapacity = 1.1 * float32 (revCacheOptions .MaxBytes ) / float32 (revCacheOptions .ShardCount )
37
+ perCacheMemoryCapacity = float32 (revCacheOptions .MaxBytes ) / float32 (revCacheOptions .ShardCount )
38
38
revCacheOptions .MaxBytes = int64 (perCacheMemoryCapacity )
39
39
}
40
40
@@ -82,16 +82,17 @@ func (sc *ShardedLRURevisionCache) Remove(docID, revID string, collectionID uint
82
82
83
83
// An LRU cache of document revision bodies, together with their channel access.
84
84
type LRURevisionCache struct {
85
- backingStores map [uint32 ]RevisionCacheBackingStore
86
- cache map [IDAndRev ]* list.Element
87
- lruList * list.List
88
- cacheHits * base.SgwIntStat
89
- cacheMisses * base.SgwIntStat
90
- cacheNumItems * base.SgwIntStat
91
- lock sync.Mutex
92
- capacity uint32
93
- memoryCapacity int64
94
- cacheMemoryBytes * base.SgwIntStat
85
+ backingStores map [uint32 ]RevisionCacheBackingStore
86
+ cache map [IDAndRev ]* list.Element
87
+ lruList * list.List
88
+ cacheHits * base.SgwIntStat
89
+ cacheMisses * base.SgwIntStat
90
+ cacheNumItems * base.SgwIntStat
91
+ lock sync.Mutex
92
+ capacity uint32 // Max number of items capacity of LRURevisionCache
93
+ memoryCapacity int64 // Max memory capacity of LRURevisionCache
94
+ currMemoryUsage base.AtomicInt // count of number of bytes used currently in the LRURevisionCache
95
+ cacheMemoryBytesStat * base.SgwIntStat // stat for overall revision cache memory usage in bytes. When using sharded cache, will be shared by all shards.
95
96
}
96
97
97
98
// The cache payload data. Stored as the Value of a list Element.
@@ -114,15 +115,15 @@ type revCacheValue struct {
114
115
func NewLRURevisionCache (revCacheOptions * RevisionCacheOptions , backingStores map [uint32 ]RevisionCacheBackingStore , cacheHitStat * base.SgwIntStat , cacheMissStat * base.SgwIntStat , cacheNumItemsStat * base.SgwIntStat , revCacheMemoryStat * base.SgwIntStat ) * LRURevisionCache {
115
116
116
117
return & LRURevisionCache {
117
- cache : map [IDAndRev ]* list.Element {},
118
- lruList : list .New (),
119
- capacity : revCacheOptions .MaxItemCount ,
120
- backingStores : backingStores ,
121
- cacheHits : cacheHitStat ,
122
- cacheMisses : cacheMissStat ,
123
- cacheNumItems : cacheNumItemsStat ,
124
- cacheMemoryBytes : revCacheMemoryStat ,
125
- memoryCapacity : revCacheOptions .MaxBytes ,
118
+ cache : map [IDAndRev ]* list.Element {},
119
+ lruList : list .New (),
120
+ capacity : revCacheOptions .MaxItemCount ,
121
+ backingStores : backingStores ,
122
+ cacheHits : cacheHitStat ,
123
+ cacheMisses : cacheMissStat ,
124
+ cacheNumItems : cacheNumItemsStat ,
125
+ cacheMemoryBytesStat : revCacheMemoryStat ,
126
+ memoryCapacity : revCacheOptions .MaxBytes ,
126
127
}
127
128
}
128
129
@@ -151,7 +152,7 @@ func (rc *LRURevisionCache) UpdateDelta(ctx context.Context, docID, revID string
151
152
if value != nil {
152
153
outGoingBytes := value .updateDelta (toDelta )
153
154
if outGoingBytes != 0 {
154
- rc .cacheMemoryBytes . Add (outGoingBytes )
155
+ rc .updateRevCacheMemoryUsage (outGoingBytes )
155
156
}
156
157
// check for memory based eviction
157
158
rc .revCacheMemoryBasedEviction ()
@@ -169,7 +170,7 @@ func (rc *LRURevisionCache) getFromCache(ctx context.Context, docID, revID strin
169
170
170
171
if ! statEvent && err == nil {
171
172
// cache miss so we had to load doc, increment memory count
172
- rc .cacheMemoryBytes . Add (value .getItemBytes ())
173
+ rc .updateRevCacheMemoryUsage (value .getItemBytes ())
173
174
// check for memory based eviction
174
175
rc .revCacheMemoryBasedEviction ()
175
176
}
@@ -205,7 +206,7 @@ func (rc *LRURevisionCache) GetActive(ctx context.Context, docID string, collect
205
206
206
207
if ! statEvent && err == nil {
207
208
// cache miss so we had to load doc, increment memory count
208
- rc .cacheMemoryBytes . Add (value .getItemBytes ())
209
+ rc .updateRevCacheMemoryUsage (value .getItemBytes ())
209
210
// check for rev cache memory based eviction
210
211
rc .revCacheMemoryBasedEviction ()
211
212
}
@@ -234,7 +235,7 @@ func (rc *LRURevisionCache) Put(ctx context.Context, docRev DocumentRevision, co
234
235
value := rc .getValue (docRev .DocID , docRev .RevID , collectionID , true )
235
236
// increment incoming bytes
236
237
docRev .CalculateBytes ()
237
- rc .cacheMemoryBytes . Add (docRev .MemoryBytes )
238
+ rc .updateRevCacheMemoryUsage (docRev .MemoryBytes )
238
239
value .store (docRev )
239
240
// check for rev cache memory based eviction
240
241
rc .revCacheMemoryBasedEviction ()
@@ -250,7 +251,7 @@ func (rc *LRURevisionCache) Upsert(ctx context.Context, docRev DocumentRevision,
250
251
if elem := rc .cache [key ]; elem != nil {
251
252
revItem := elem .Value .(* revCacheValue )
252
253
// decrement item bytes by the removed item
253
- rc .cacheMemoryBytes . Add (- revItem .getItemBytes ())
254
+ rc .updateRevCacheMemoryUsage (- revItem .getItemBytes ())
254
255
rc .lruList .Remove (elem )
255
256
newItem = false
256
257
}
@@ -275,13 +276,13 @@ func (rc *LRURevisionCache) Upsert(ctx context.Context, docRev DocumentRevision,
275
276
276
277
docRev .CalculateBytes ()
277
278
// add new item bytes to overall count
278
- rc .cacheMemoryBytes . Add (docRev .MemoryBytes )
279
+ rc .updateRevCacheMemoryUsage (docRev .MemoryBytes )
279
280
value .store (docRev )
280
281
281
282
// check we aren't over memory capacity, if so perform eviction
282
283
numItemsRemoved = 0
283
284
if rc .memoryCapacity > 0 {
284
- for rc .cacheMemoryBytes .Value () > rc .memoryCapacity {
285
+ for rc .currMemoryUsage .Value () > rc .memoryCapacity {
285
286
rc .purgeOldest_ ()
286
287
numItemsRemoved ++
287
288
}
@@ -332,7 +333,7 @@ func (rc *LRURevisionCache) Remove(docID, revID string, collectionID uint32) {
332
333
rc .lruList .Remove (element )
333
334
// decrement the overall memory bytes count
334
335
revItem := element .Value .(* revCacheValue )
335
- rc .cacheMemoryBytes . Add (- revItem .getItemBytes ())
336
+ rc .updateRevCacheMemoryUsage (- revItem .getItemBytes ())
336
337
delete (rc .cache , key )
337
338
rc .cacheNumItems .Add (- 1 )
338
339
}
@@ -352,7 +353,7 @@ func (rc *LRURevisionCache) purgeOldest_() {
352
353
value := rc .lruList .Remove (rc .lruList .Back ()).(* revCacheValue )
353
354
delete (rc .cache , value .key )
354
355
// decrement memory overall size
355
- rc .cacheMemoryBytes . Add (- value .getItemBytes ())
356
+ rc .updateRevCacheMemoryUsage (- value .getItemBytes ())
356
357
}
357
358
358
359
// Gets the body etc. out of a revCacheValue. If they aren't present already, the loader func
@@ -531,7 +532,7 @@ func (delta *RevisionDelta) CalculateDeltaBytes() {
531
532
// revCacheMemoryBasedEviction checks for rev cache eviction, if required calls performEviction which will acquire lock to evict
532
533
func (rc * LRURevisionCache ) revCacheMemoryBasedEviction () {
533
534
// if memory capacity is not set, don't check for eviction this way
534
- if rc .memoryCapacity > 0 && rc .cacheMemoryBytes .Value () > rc .memoryCapacity {
535
+ if rc .memoryCapacity > 0 && rc .currMemoryUsage .Value () > rc .memoryCapacity {
535
536
rc .performEviction ()
536
537
}
537
538
}
@@ -541,9 +542,19 @@ func (rc *LRURevisionCache) performEviction() {
541
542
rc .lock .Lock ()
542
543
defer rc .lock .Unlock ()
543
544
var numItemsRemoved int64
544
- for rc .cacheMemoryBytes .Value () > rc .memoryCapacity {
545
+ for rc .currMemoryUsage .Value () > rc .memoryCapacity {
545
546
rc .purgeOldest_ ()
546
547
numItemsRemoved ++
547
548
}
548
549
rc .cacheNumItems .Add (- numItemsRemoved )
549
550
}
551
+
552
+ // updateRevCacheMemoryUsage atomically increases overall memory usage for cache and the actual rev cache objects usage
553
+ func (rc * LRURevisionCache ) updateRevCacheMemoryUsage (bytesCount int64 ) {
554
+ // We need to keep track of the current LRURevisionCache memory usage AND the overall usage of the cache. We need
555
+ // overall memory usage for the stat added to show rev cache usage plus we need the current rev cache capacity of the
556
+ // LRURevisionCache object for sharding the rev cache. This way we can perform eviction on per shard basis much like
557
+ // we do with the number of items capacity eviction
558
+ rc .currMemoryUsage .Add (bytesCount )
559
+ rc .cacheMemoryBytesStat .Add (bytesCount )
560
+ }
0 commit comments