Skip to content

Commit ccbba07

Browse files
committed
Feat(common): optimize cache promotion and demotion
Signed-off-by: zztaki <[email protected]>
1 parent bfd5acb commit ccbba07

File tree

2 files changed

+127
-19
lines changed

2 files changed

+127
-19
lines changed

src/common/lru_cache.h

+5-19
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class LRUCache : public LRUCacheInterface<K, V> {
204204
void Remove(const K &key) override;
205205

206206
/*
207-
* @brief Get the first key that $value = value
207+
* @brief Get the first key that $value = value from lru tail to head
208208
*
209209
* @param[in] value
210210
* @param[out] key
@@ -429,10 +429,7 @@ void LRUCache<K, V, KeyTraits, ValueTraits>::RemoveLocked(const K &key) {
429429
template <typename K, typename V, typename KeyTraits, typename ValueTraits>
430430
void LRUCache<K, V, KeyTraits, ValueTraits>::MoveToFront(
431431
const typename std::list<Item>::iterator &elem) {
432-
Item duplica{elem->key, elem->value};
433-
ll_.erase(elem);
434-
ll_.push_front(duplica);
435-
cache_[*(duplica.key)] = ll_.begin();
432+
ll_.splice(ll_.begin(), ll_, elem);
436433
}
437434

438435
template <typename K, typename V, typename KeyTraits, typename ValueTraits>
@@ -699,16 +696,8 @@ bool SglLRUCache<K, KeyTraits>::MoveBack(const K &key) {
699696
if (iter == cache_.end()) {
700697
return false;
701698
}
702-
// delete the old value
703-
RemoveElement(iter->second);
704-
// put new value at tail
705-
ll_.push_back(key);
706-
cache_[key] = --ll_.end();
707-
size_++;
708-
if (cacheMetrics_ != nullptr) {
709-
cacheMetrics_->UpdateAddToCacheCount();
710-
cacheMetrics_->UpdateAddToCacheBytes(KeyTraits::CountBytes(key));
711-
}
699+
// move key to list tail
700+
ll_.splice(ll_.end(), ll_, iter->second);
712701
return true;
713702
}
714703

@@ -806,10 +795,7 @@ void SglLRUCache<K, KeyTraits>::RemoveLocked(const K &key) {
806795
template <typename K, typename KeyTraits>
807796
void SglLRUCache<K, KeyTraits>::MoveToFront(
808797
const typename std::list<K>::iterator &elem) {
809-
K tmp = *elem;
810-
ll_.erase(elem);
811-
ll_.emplace_front(tmp);
812-
cache_[tmp] = ll_.begin();
798+
ll_.splice(ll_.begin(), ll_, elem);
813799
}
814800

815801
template <typename K, typename KeyTraits>

test/common/lru_cache_test.cpp

+122
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,51 @@ TEST(CaCheTest, TestCacheGetLastKVWithFunction) {
212212
ASSERT_EQ(false, ok);
213213
}
214214

215+
TEST(CaCheTest, TestCachePromotion) {
216+
auto cache = std::make_shared<LRUCache<int, int>>(
217+
std::make_shared<CacheMetrics>("LruCache"));
218+
219+
int k, v;
220+
for (int k = 0; k < 5; k++) {
221+
v = k;
222+
cache->Put(k, v);
223+
}
224+
// now cache list: 4 3 2 1 0
225+
226+
for (int k = 0; k < 5; k += 2) {
227+
cache->Get(k, &v);
228+
ASSERT_EQ(k, v);
229+
}
230+
// now cache list: 4 2 0 3 1
231+
232+
cache->GetLast(&k, &v);
233+
cache->Remove(k);;
234+
ASSERT_EQ(1, k);
235+
ASSERT_EQ(1, v);
236+
237+
cache->GetLast(&k, &v);
238+
cache->Remove(k);;
239+
ASSERT_EQ(3, k);
240+
ASSERT_EQ(3, v);
241+
242+
cache->GetLast(&k, &v);
243+
cache->Remove(k);;
244+
ASSERT_EQ(0, k);
245+
ASSERT_EQ(0, v);
246+
247+
cache->GetLast(&k, &v);
248+
cache->Remove(k);;
249+
ASSERT_EQ(2, k);
250+
ASSERT_EQ(2, v);
251+
252+
cache->GetLast(&k, &v);
253+
cache->Remove(k);;
254+
ASSERT_EQ(4, k);
255+
ASSERT_EQ(4, v);
256+
257+
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheCount.get_value());
258+
}
259+
215260
TEST(SglCaCheTest, TestGetBefore) {
216261
auto cache = std::make_shared<SglLRUCache<int>>(
217262
std::make_shared<CacheMetrics>("LruCache"));
@@ -302,6 +347,83 @@ TEST(SglCaCheTest, TestCacheHitAndMissMetric) {
302347
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheMiss.get_value());
303348
}
304349

350+
TEST(SglCaCheTest, TestCachePromotionAndDemotion) {
351+
auto cache = std::make_shared<SglLRUCache<int>>(
352+
std::make_shared<CacheMetrics>("LruCache"));
353+
354+
// test promotion
355+
{
356+
int k;
357+
for (int k = 0; k < 5; k++) {
358+
cache->Put(k);
359+
}
360+
// now cache list: 4 3 2 1 0
361+
362+
for (int k = 0; k < 5; k += 2) {
363+
ASSERT_EQ(cache->IsCached(k), true);
364+
}
365+
// now cache list: 4 2 0 3 1
366+
367+
cache->GetBack(&k);
368+
cache->Remove(k);;
369+
ASSERT_EQ(1, k);
370+
371+
cache->GetBack(&k);
372+
cache->Remove(k);;
373+
ASSERT_EQ(3, k);
374+
375+
cache->GetBack(&k);
376+
cache->Remove(k);;
377+
ASSERT_EQ(0, k);
378+
379+
cache->GetBack(&k);
380+
cache->Remove(k);;
381+
ASSERT_EQ(2, k);
382+
383+
cache->GetBack(&k);
384+
cache->Remove(k);;
385+
ASSERT_EQ(4, k);
386+
387+
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheCount.get_value());
388+
}
389+
390+
// test demotion
391+
{
392+
int k;
393+
for (int k = 0; k < 5; k++) {
394+
cache->Put(k);
395+
}
396+
// now cache list: 4 3 2 1 0
397+
398+
for (int k = 4; k >= 0; k -= 2) {
399+
ASSERT_EQ(cache->MoveBack(k), true);
400+
}
401+
// now cache list: 3 1 4 2 0
402+
403+
cache->GetBack(&k);
404+
cache->Remove(k);;
405+
ASSERT_EQ(0, k);
406+
407+
cache->GetBack(&k);
408+
cache->Remove(k);;
409+
ASSERT_EQ(2, k);
410+
411+
cache->GetBack(&k);
412+
cache->Remove(k);;
413+
ASSERT_EQ(4, k);
414+
415+
cache->GetBack(&k);
416+
cache->Remove(k);;
417+
ASSERT_EQ(1, k);
418+
419+
cache->GetBack(&k);
420+
cache->Remove(k);;
421+
ASSERT_EQ(3, k);
422+
423+
ASSERT_EQ(0, cache->GetCacheMetrics()->cacheCount.get_value());
424+
}
425+
}
426+
305427
TEST(TimedCaCheTest, test_base) {
306428
int maxCount = 5;
307429
int timeOutSec = 0;

0 commit comments

Comments
 (0)