Browse Source

Add TotalSize and Size methods

Раньше метод GetTotalSize() был только в TLRUList, хотя TSizeProvider присутствовал также в TLRUList
Добавил GetTotalSize() во все листы (в том числе TLWList), а также метод GetSize(), который возвращает текущее количество

Также добавил эти методы в сами TCache и TThreadSafeCache
c103617d7259841e1c273cadd8dbf0bb019e52dc
ivanmautin 10 months ago
parent
commit
db9340f745
3 changed files with 109 additions and 12 deletions
  1. 26 10
      library/cpp/cache/cache.h
  2. 10 0
      library/cpp/cache/thread_safe_cache.h
  3. 73 2
      library/cpp/cache/ut/cache_ut.cpp

+ 26 - 10
library/cpp/cache/cache.h

@@ -124,11 +124,11 @@ public:
         List.PushBack(item);
     }
 
-    size_t GetSize() const {
+    [[nodiscard]] size_t GetSize() const {
         return ItemsAmount;
     }
 
-    size_t GetTotalSize() const {
+    [[nodiscard]] size_t GetTotalSize() const {
         return TotalSize;
     }
 
@@ -157,7 +157,8 @@ public:
     TLFUList(size_t maxSize, const TSizeProvider& sizeProvider = TSizeProvider())
         : List()
         , SizeProvider(sizeProvider)
-        , ListSize(0)
+        , ItemsAmount(0)
+        , TotalSize(0)
         , MaxSize(maxSize)
     {
     }
@@ -228,14 +229,15 @@ public:
 public:
     TItem* Insert(TItem* item) {
         List.PushBack(item); // give a chance for promotion
-        ListSize += SizeProvider(item->Value);
+        ++ItemsAmount;
+        TotalSize += SizeProvider(item->Value);
 
         return RemoveIfOverflown();
     }
 
     TItem* RemoveIfOverflown() {
         TItem* deleted = nullptr;
-        if (ListSize > MaxSize) {
+        if (TotalSize > MaxSize && ItemsAmount > 1) {
             deleted = GetLeastFrequentlyUsed();
             Erase(deleted);
         }
@@ -250,7 +252,8 @@ public:
 
     void Erase(TItem* item) {
         item->Unlink();
-        ListSize -= SizeProvider(item->Value);
+        --ItemsAmount;
+        TotalSize -= SizeProvider(item->Value);
     }
 
     void Promote(TItem* item) {
@@ -262,8 +265,12 @@ public:
         item->LinkBefore(&*it);
     }
 
-    size_t GetSize() const {
-        return ListSize;
+    [[nodiscard]] size_t GetSize() const {
+        return ItemsAmount;
+    }
+
+    [[nodiscard]] size_t GetTotalSize() const {
+        return TotalSize;
     }
 
     size_t GetMaxSize() const {
@@ -280,7 +287,8 @@ private:
     typedef TIntrusiveList<TItem> TListType;
     TListType List;
     TSizeProvider SizeProvider;
-    size_t ListSize;
+    size_t ItemsAmount;
+    size_t TotalSize;
     size_t MaxSize;
 };
 
@@ -413,6 +421,10 @@ public:
         return Size;
     }
 
+    [[nodiscard]] size_t GetTotalSize() const {
+        return Size;
+    }
+
     size_t GetMaxSize() const {
         return MaxSize;
     }
@@ -515,10 +527,14 @@ public:
         Clear();
     }
 
-    size_t Size() const {
+    [[nodiscard]] size_t Size() const {
         return Index.size();
     }
 
+    [[nodiscard]] size_t TotalSize() const {
+        return List.GetTotalSize();
+    }
+
     TIterator Begin() const {
         return TIterator(Index.begin());
     }

+ 10 - 0
library/cpp/cache/thread_safe_cache.h

@@ -96,6 +96,16 @@ namespace NPrivate {
             return TThreadSafeCacheSingleton<TCallbacks>::Clear();
         }
 
+        size_t Size() const {
+            TReadGuard r(Mutex);
+            return Cache.Size();
+        }
+
+        size_t TotalSize() const {
+            TReadGuard r(Mutex);
+            return Cache.TotalSize();
+        }
+
         size_t GetMaxSize() const {
             TReadGuard w(Mutex);
             return Cache.GetMaxSize();

+ 73 - 2
library/cpp/cache/ut/cache_ut.cpp

@@ -15,10 +15,14 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
 
         TListType::TItem x1(1, "ttt");
         list.Insert(&x1);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 1);
         UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
 
         TListType::TItem x2(2, "yyy");
         list.Insert(&x2);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
 
         list.Promote(list.GetOldest());
@@ -26,6 +30,8 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
 
         TListType::TItem x3(3, "zzz");
         list.Insert(&x3);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
     }
 
@@ -39,12 +45,16 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         list.Insert(&x1);
         while (list.RemoveIfOverflown()) {
         }
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 3);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 1);
         UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
 
         TListType::TItem x2(2, "yyy");
         list.Insert(&x2);
         while (list.RemoveIfOverflown()) {
         }
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 6);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
 
         list.Promote(list.GetOldest());
@@ -56,13 +66,25 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         list.Insert(&x3);
         while (list.RemoveIfOverflown()) {
         }
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 6);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 1);
 
         TListType::TItem x4(4, "longlong");
         list.Insert(&x4);
         while (list.RemoveIfOverflown()) {
         }
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 8);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 1);
         UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 4);
+
+        TListType::TItem x5(5, "xxx");
+        list.Insert(&x5);
+        while (list.RemoveIfOverflown()) {
+        }
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 3);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 1);
+        UNIT_ASSERT_EQUAL(list.GetOldest()->Key, 5);
     }
 
     Y_UNIT_TEST(LFUListTest) {
@@ -71,10 +93,14 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
 
         TListType::TItem x1(1, "ttt");
         list.Insert(&x1);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 1);
         UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
 
         TListType::TItem x2(2, "yyy");
         list.Insert(&x2);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
 
         list.Promote(list.GetLeastFrequentlyUsed());
@@ -82,6 +108,8 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
 
         TListType::TItem x3(3, "zzz");
         list.Insert(&x3);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
+        UNIT_ASSERT_EQUAL(list.GetSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetLeastFrequentlyUsed()->Key, 1);
     }
 
@@ -92,25 +120,30 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         TListType::TItem x1(1, "tt");
         list.Insert(&x1);
         UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
         UNIT_ASSERT_EQUAL(list.GetSize(), 1);
 
         TListType::TItem x2(2, "yyyy");
         list.Insert(&x2);
         UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetSize(), 2);
 
         TListType::TItem x3(3, "z");
         list.Insert(&x3);
         UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 1);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetSize(), 2);
 
         TListType::TItem x4(4, "xxxxxx");
         list.Insert(&x4);
         UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 2);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 2);
         UNIT_ASSERT_EQUAL(list.GetSize(), 2);
 
         list.Erase(&x2);
         UNIT_ASSERT_EQUAL(list.GetLightest()->Key, 4);
+        UNIT_ASSERT_EQUAL(list.GetTotalSize(), 1);
         UNIT_ASSERT_EQUAL(list.GetSize(), 1);
     }
 
@@ -118,11 +151,17 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         typedef TLRUCache<int, TString> TCache;
         TCache s(2); // size 2
         s.Insert(1, "abcd");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 1);
+        UNIT_ASSERT_EQUAL(s.Size(), 1);
         UNIT_ASSERT(s.Find(1) != s.End());
         UNIT_ASSERT_EQUAL(*s.Find(1), "abcd");
         s.Insert(2, "defg");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 2);
+        UNIT_ASSERT_EQUAL(s.Size(), 2);
         UNIT_ASSERT(s.GetOldest() == "abcd");
         s.Insert(3, "hjkl");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 2);
+        UNIT_ASSERT_EQUAL(s.Size(), 2);
         UNIT_ASSERT(s.GetOldest() == "defg");
         // key 1 will be deleted
         UNIT_ASSERT(s.Find(1) == s.End());
@@ -135,9 +174,13 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         UNIT_ASSERT(*s.Find(3) == "hjkl");
         s.Update(3, "abcd");
         UNIT_ASSERT(*s.Find(3) == "abcd");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 2);
+        UNIT_ASSERT_EQUAL(s.Size(), 2);
 
         TCache::TIterator it = s.Find(3);
         s.Erase(it);
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 1);
+        UNIT_ASSERT_EQUAL(s.Size(), 1);
         UNIT_ASSERT(s.Find(3) == s.End());
     }
 
@@ -145,13 +188,21 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         typedef TLRUCache<int, TString, TNoopDelete, size_t(*)(const TString&)> TCache;
         TCache s(10, false, [](auto& string) { return string.size(); }); // size 10
         s.Insert(1, "abcd");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 4);
+        UNIT_ASSERT_EQUAL(s.Size(), 1);
         UNIT_ASSERT(s.Find(1) != s.End());
         UNIT_ASSERT_EQUAL(*s.Find(1), "abcd");
         s.Insert(2, "defg");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 8);
+        UNIT_ASSERT_EQUAL(s.Size(), 2);
         UNIT_ASSERT(s.GetOldest() == "abcd");
         s.Insert(3, "2c");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 10);
+        UNIT_ASSERT_EQUAL(s.Size(), 3);
         UNIT_ASSERT(s.GetOldest() == "abcd");
         s.Insert(4, "hjkl");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 10);
+        UNIT_ASSERT_EQUAL(s.Size(), 3);
         UNIT_ASSERT(s.GetOldest() == "defg");
         // key 1 will be deleted
         UNIT_ASSERT(s.Find(1) == s.End());
@@ -165,10 +216,14 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         UNIT_ASSERT(!s.Insert(3, "abcd"));
         UNIT_ASSERT(*s.Find(3) == "2c");
         s.Update(3, "abcd");
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 8);
+        UNIT_ASSERT_EQUAL(s.Size(), 2);
         UNIT_ASSERT(*s.Find(3) == "abcd");
 
         TCache::TIterator it = s.Find(3);
         s.Erase(it);
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 4);
+        UNIT_ASSERT_EQUAL(s.Size(), 1);
         UNIT_ASSERT(s.Find(3) == s.End());
     }
 
@@ -317,10 +372,14 @@ Y_UNIT_TEST_SUITE(TCacheTest) {
         UNIT_ASSERT(s.Insert(1, "abcd"));
         UNIT_ASSERT(s.Insert(1, "bcde"));
         UNIT_ASSERT(s.Insert(2, "fghi"));
-        UNIT_ASSERT(s.Insert(2, "ghij"));
         // (1, "abcd") will be deleted
-        UNIT_ASSERT(*s.Find(1) == "bcde");
+        UNIT_ASSERT(s.Insert(2, "ghij"));
+
+        UNIT_ASSERT_EQUAL(s.TotalSize(), 3);
+        UNIT_ASSERT_EQUAL(s.Size(), 3);
+
         // (1, "bcde") will be promoted
+        UNIT_ASSERT(*s.Find(1) == "bcde");
         UNIT_ASSERT(*s.FindOldest() == "fghi");
     }
 
@@ -449,6 +508,8 @@ Y_UNIT_TEST_SUITE(TThreadSafeCacheTest) {
         cache.Update(2, MakeAtomicShared<TString>("hjk"));
         item = cache.Get(2);
 
+        UNIT_ASSERT_EQUAL(cache.TotalSize(), 1);
+        UNIT_ASSERT_EQUAL(cache.Size(), 1);
         UNIT_ASSERT(callbacks.Creations == 0);
         UNIT_ASSERT(*item == "hjk");
     }
@@ -484,6 +545,8 @@ Y_UNIT_TEST_SUITE(TThreadSafeCacheUnsafeTest) {
                 UNIT_ASSERT(*data == VALS[i]);
             }
         }
+        UNIT_ASSERT_EQUAL(cache.TotalSize(), Y_ARRAY_SIZE(VALS) - 1);
+        UNIT_ASSERT_EQUAL(cache.Size(), Y_ARRAY_SIZE(VALS) - 1);
     }
 }
 
@@ -532,6 +595,8 @@ Y_UNIT_TEST_SUITE(TThreadSafeLRUCacheTest) {
         cache.Update(2, MakeAtomicShared<TString>("hjk"));
         item = cache.Get(2);
 
+        UNIT_ASSERT_EQUAL(cache.TotalSize(), 1);
+        UNIT_ASSERT_EQUAL(cache.Size(), 1);
         UNIT_ASSERT(callbacks.Creations == 0);
         UNIT_ASSERT(*item == "hjk");
     }
@@ -630,17 +695,23 @@ Y_UNIT_TEST_SUITE(TThreadSafeLRUCacheTest) {
         UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
         UNIT_ASSERT(*item == "one");
 
+        UNIT_ASSERT_EQUAL(cache.TotalSize(), 3);
+        UNIT_ASSERT_EQUAL(cache.Size(), 3);
         cache.SetMaxSize(4);
 
         item = cache.Get(0);
         expectedCreations++;
         UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
         UNIT_ASSERT(*item == "zero");
+        UNIT_ASSERT_EQUAL(cache.TotalSize(), 4);
+        UNIT_ASSERT_EQUAL(cache.Size(), 4);
 
         item = cache.Get(4);
         expectedCreations++;
         UNIT_ASSERT_EQUAL(callbacks.Creations, expectedCreations);
         UNIT_ASSERT(*item == "four");
+        UNIT_ASSERT_EQUAL(cache.TotalSize(), 4);
+        UNIT_ASSERT_EQUAL(cache.Size(), 4);
 
         item = cache.Get(3);
         expectedCreations++;