Skip to content

Commit f287547

Browse files
Concurrent turmoil no longer leads to double evaluation
An item being added to the cache is never evicted due to concurrent turmoil. LRU eviction heuristics was changed to only evict items with non-zero cost.
1 parent d3a129d commit f287547

File tree

2 files changed

+34
-51
lines changed

2 files changed

+34
-51
lines changed

src/lrucache.h

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class lru_cache {
211211
log_debug("_current_cost after increase: " << _current_cost);
212212
const auto costLimit = std::max(_max_cost, extra_cost);
213213
while (_current_cost > costLimit) {
214-
dropLast();
214+
dropLRU();
215215
}
216216
log_debug("settled _current_cost: " << _current_cost);
217217
}
@@ -223,14 +223,28 @@ class lru_cache {
223223
log_debug("_current_cost after decrease: " << _current_cost);
224224
}
225225

226-
void dropLast() {
227-
log_debug_func_call("lru_cache::dropLast");
228-
auto list_it = _cache_items_list.back();
229-
const auto key = _cache_items_list.back().first;
230-
log_debug("evicting entry with key: " << key);
231-
decreaseCost(CostEstimation::cost(list_it.second));
232-
_cache_items_map.erase(key);
233-
_cache_items_list.pop_back();
226+
list_iterator_t getLRUItem() {
227+
for ( list_iterator_t it = _cache_items_list.end(); it != _cache_items_list.begin(); ) {
228+
--it;
229+
if ( CostEstimation::cost(it->second) > 0 )
230+
return it;
231+
}
232+
return _cache_items_list.end();
233+
}
234+
235+
void dropLRU() {
236+
log_debug_func_call("lru_cache::dropLRU");
237+
const auto lruIt = getLRUItem();
238+
if ( lruIt == _cache_items_list.end() )
239+
return;
240+
const auto key = lruIt->first;
241+
const auto itemCost = CostEstimation::cost(lruIt->second);
242+
if ( itemCost > 0 ) {
243+
log_debug("evicting entry with key: " << key);
244+
decreaseCost(itemCost);
245+
_cache_items_map.erase(key);
246+
_cache_items_list.erase(lruIt);
247+
}
234248
}
235249

236250
void putMissing(const key_t& key, const value_t& value) {

test/concurrentcache.cpp

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ thread#0: _current_cost after decrease: 1
193193
thread#0: }
194194
thread#0: lru_cache::increaseCost(1) {
195195
thread#0: _current_cost after increase: 2
196-
thread#0: lru_cache::dropLast() {
196+
thread#0: lru_cache::dropLRU() {
197197
thread#0: evicting entry with key: 3
198198
thread#0: lru_cache::decreaseCost(1) {
199199
thread#0: _current_cost after decrease: 1
@@ -361,13 +361,13 @@ R"(thread#0: ConcurrentCache::setMaxCost(500) {
361361
thread#0: entered synchronized section
362362
thread#0: lru_cache::increaseCost(0) {
363363
thread#0: _current_cost after increase: 900
364-
thread#0: lru_cache::dropLast() {
364+
thread#0: lru_cache::dropLRU() {
365365
thread#0: evicting entry with key: 5
366366
thread#0: lru_cache::decreaseCost(150) {
367367
thread#0: _current_cost after decrease: 750
368368
thread#0: }
369369
thread#0: }
370-
thread#0: lru_cache::dropLast() {
370+
thread#0: lru_cache::dropLRU() {
371371
thread#0: evicting entry with key: 10
372372
thread#0: lru_cache::decreaseCost(300) {
373373
thread#0: _current_cost after decrease: 450
@@ -393,19 +393,19 @@ R"(thread#0: ConcurrentCache::setMaxCost(400) {
393393
thread#0: entered synchronized section
394394
thread#0: lru_cache::increaseCost(0) {
395395
thread#0: _current_cost after increase: 900
396-
thread#0: lru_cache::dropLast() {
396+
thread#0: lru_cache::dropLRU() {
397397
thread#0: evicting entry with key: 5
398398
thread#0: lru_cache::decreaseCost(150) {
399399
thread#0: _current_cost after decrease: 750
400400
thread#0: }
401401
thread#0: }
402-
thread#0: lru_cache::dropLast() {
402+
thread#0: lru_cache::dropLRU() {
403403
thread#0: evicting entry with key: 10
404404
thread#0: lru_cache::decreaseCost(300) {
405405
thread#0: _current_cost after decrease: 450
406406
thread#0: }
407407
thread#0: }
408-
thread#0: lru_cache::dropLast() {
408+
thread#0: lru_cache::dropLRU() {
409409
thread#0: evicting entry with key: 15
410410
thread#0: lru_cache::decreaseCost(450) {
411411
thread#0: _current_cost after decrease: 0
@@ -625,13 +625,7 @@ s : It was a cache miss. Going to obtain the value...
625625
f: }
626626
f: lru_cache::increaseCost(60) {
627627
f: _current_cost after increase: 210
628-
f: lru_cache::dropLast() {
629-
f: evicting entry with key: 6
630-
f: lru_cache::decreaseCost(0) {
631-
f: _current_cost after decrease: 210
632-
f: }
633-
f: }
634-
f: lru_cache::dropLast() {
628+
f: lru_cache::dropLRU() {
635629
f: evicting entry with key: 5
636630
f: lru_cache::decreaseCost(150) {
637631
f: _current_cost after decrease: 60
@@ -649,20 +643,15 @@ s : It was a cache miss. Going to obtain the value...
649643
x : ConcurrentCache::getCacheSlot(6) {
650644
x : entered synchronized section
651645
x : lru_cache::getOrPut(6) {
652-
x : not in cache, adding...
653-
x : lru_cache::putMissing(6) {
654-
x : lru_cache::increaseCost(0) {
655-
x : _current_cost after increase: 60
656-
x : settled _current_cost: 60
657-
x : }
658-
x : }
646+
x : already in cache, moved to the beginning of the LRU list.
659647
x : }
660648
x : exiting synchronized section
661649
x : }
662650
x : Obtained the cache slot
663-
x : It was a cache miss. Going to obtain the value...
651+
x : Waiting for result...
664652
s : Value was successfully obtained.
665653
s : Made the value available for concurrent access.
654+
x : } (return value: 60)
666655
s : Computing the cost of the new entry...
667656
s : cost=180
668657
s : ConcurrentCache::finalizeCacheMiss(6) {
@@ -673,7 +662,7 @@ s : _current_cost after decrease: 60
673662
s : }
674663
s : lru_cache::increaseCost(180) {
675664
s : _current_cost after increase: 240
676-
s : lru_cache::dropLast() {
665+
s : lru_cache::dropLRU() {
677666
s : evicting entry with key: 2
678667
s : lru_cache::decreaseCost(60) {
679668
s : _current_cost after decrease: 180
@@ -687,26 +676,6 @@ s : }
687676
s : Done. Cache cost is at 180
688677
s : Returning immediately...
689678
s : } (return value: 60)
690-
x : Value was successfully obtained.
691-
x : Made the value available for concurrent access.
692-
x : Computing the cost of the new entry...
693-
x : cost=180
694-
x : ConcurrentCache::finalizeCacheMiss(6) {
695-
x : entered synchronized section
696-
x : lru_cache::put(6) {
697-
x : lru_cache::decreaseCost(180) {
698-
x : _current_cost after decrease: 0
699-
x : }
700-
x : lru_cache::increaseCost(180) {
701-
x : _current_cost after increase: 180
702-
x : settled _current_cost: 180
703-
x : }
704-
x : }
705-
x : exiting synchronized section
706-
x : }
707-
x : Done. Cache cost is at 180
708-
x : Returning immediately...
709-
x : } (return value: 60)
710679
)";
711680

712681
zim::ConcurrentCache<int, size_t, CostAs3xValue> cache(200);

0 commit comments

Comments
 (0)