Skip to content

Commit

Permalink
[Perf](common): optimize cache promotion and demotion
Browse files Browse the repository at this point in the history
Signed-off-by: zztaki <[email protected]>
  • Loading branch information
zztaki committed Dec 14, 2023
1 parent bfd5acb commit 76d8db6
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 19 deletions.
24 changes: 5 additions & 19 deletions src/common/lru_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class LRUCache : public LRUCacheInterface<K, V> {
void Remove(const K &key) override;

/*
* @brief Get the first key that $value = value
* @brief Get the first key that $value = value from lru tail to head
*
* @param[in] value
* @param[out] key
Expand Down Expand Up @@ -429,10 +429,7 @@ void LRUCache<K, V, KeyTraits, ValueTraits>::RemoveLocked(const K &key) {
template <typename K, typename V, typename KeyTraits, typename ValueTraits>
void LRUCache<K, V, KeyTraits, ValueTraits>::MoveToFront(
const typename std::list<Item>::iterator &elem) {
Item duplica{elem->key, elem->value};
ll_.erase(elem);
ll_.push_front(duplica);
cache_[*(duplica.key)] = ll_.begin();
ll_.splice(ll_.begin(), ll_, elem);
}

template <typename K, typename V, typename KeyTraits, typename ValueTraits>
Expand Down Expand Up @@ -699,16 +696,8 @@ bool SglLRUCache<K, KeyTraits>::MoveBack(const K &key) {
if (iter == cache_.end()) {
return false;
}
// delete the old value
RemoveElement(iter->second);
// put new value at tail
ll_.push_back(key);
cache_[key] = --ll_.end();
size_++;
if (cacheMetrics_ != nullptr) {
cacheMetrics_->UpdateAddToCacheCount();
cacheMetrics_->UpdateAddToCacheBytes(KeyTraits::CountBytes(key));
}
// move key to list tail
ll_.splice(ll_.end(), ll_, iter->second);
return true;
}

Expand Down Expand Up @@ -806,10 +795,7 @@ void SglLRUCache<K, KeyTraits>::RemoveLocked(const K &key) {
template <typename K, typename KeyTraits>
void SglLRUCache<K, KeyTraits>::MoveToFront(
const typename std::list<K>::iterator &elem) {
K tmp = *elem;
ll_.erase(elem);
ll_.emplace_front(tmp);
cache_[tmp] = ll_.begin();
ll_.splice(ll_.begin(), ll_, elem);
}

template <typename K, typename KeyTraits>
Expand Down
132 changes: 132 additions & 0 deletions test/common/lru_cache_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,53 @@ TEST(CaCheTest, TestCacheGetLastKVWithFunction) {
ASSERT_EQ(false, ok);
}

TEST(CaCheTest, TestCachePromotion) {
auto cache = std::make_shared<LRUCache<int, int>>(
std::make_shared<CacheMetrics>("LruCache"));

int k, v;
for (int k = 0; k < 5; k++) {
v = k;
cache->Put(k, v);
}
ASSERT_EQ(cache->Size(), 5);
// now cache list: 4 3 2 1 0

for (int k = 0; k < 5; k += 2) {
cache->Get(k, &v);
ASSERT_EQ(k, v);
}
// now cache list: 4 2 0 3 1

cache->GetLast(&k, &v);
cache->Remove(k);
ASSERT_EQ(1, k);
ASSERT_EQ(1, v);

cache->GetLast(&k, &v);
cache->Remove(k);
ASSERT_EQ(3, k);
ASSERT_EQ(3, v);

cache->GetLast(&k, &v);
cache->Remove(k);
ASSERT_EQ(0, k);
ASSERT_EQ(0, v);

cache->GetLast(&k, &v);
cache->Remove(k);
ASSERT_EQ(2, k);
ASSERT_EQ(2, v);

cache->GetLast(&k, &v);
cache->Remove(k);
ASSERT_EQ(4, k);
ASSERT_EQ(4, v);

ASSERT_EQ(0, cache->GetCacheMetrics()->cacheCount.get_value());
ASSERT_EQ(0, cache->Size());
}

TEST(SglCaCheTest, TestGetBefore) {
auto cache = std::make_shared<SglLRUCache<int>>(
std::make_shared<CacheMetrics>("LruCache"));
Expand Down Expand Up @@ -302,6 +349,85 @@ TEST(SglCaCheTest, TestCacheHitAndMissMetric) {
ASSERT_EQ(10, cache->GetCacheMetrics()->cacheMiss.get_value());
}

TEST(SglCaCheTest, TestCachePromotionAndDemotion) {
auto cache = std::make_shared<SglLRUCache<int>>(
std::make_shared<CacheMetrics>("LruCache"));

// test promotion
{
int k;
for (int k = 0; k < 5; k++) {
cache->Put(k);
}
// now cache list: 4 3 2 1 0

for (int k = 0; k < 5; k += 2) {
ASSERT_EQ(cache->IsCached(k), true);
}
// now cache list: 4 2 0 3 1

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(1, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(3, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(0, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(2, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(4, k);

ASSERT_EQ(0, cache->GetCacheMetrics()->cacheCount.get_value());
}

// test demotion
{
int k;
for (int k = 0; k < 5; k++) {
cache->Put(k);
}
// now cache list: 4 3 2 1 0

ASSERT_EQ(cache->MoveBack(10), false);
for (int k = 4; k >= 0; k -= 2) {
ASSERT_EQ(cache->MoveBack(k), true);
}
// now cache list: 3 1 4 2 0

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(0, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(2, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(4, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(1, k);

cache->GetBack(&k);
cache->Remove(k);
ASSERT_EQ(3, k);

ASSERT_EQ(0, cache->GetCacheMetrics()->cacheCount.get_value());
ASSERT_EQ(0, cache->Size());
}
}

TEST(TimedCaCheTest, test_base) {
int maxCount = 5;
int timeOutSec = 0;
Expand All @@ -328,6 +454,12 @@ TEST(TimedCaCheTest, test_base) {
ASSERT_TRUE(cache->Get(std::to_string(i), &res));
ASSERT_EQ(std::to_string(i), res);
}

// remove
for (int i = 2; i <= maxCount + 1; i++) {
cache->Remove(std::to_string(i));
}
ASSERT_EQ(0, cache->Size());
}

TEST(TimedCaCheTest, test_timeout) {
Expand Down

0 comments on commit 76d8db6

Please sign in to comment.