Skip to content

Commit 649bff3

Browse files
QUICHE teamcopybara-github
authored andcommitted
Add UpdateMaxSize to QuicLRUCache.
This change allows the maximum size of the QuicLRUCache to be updated after creation. If the new maximum size is smaller than the current number of elements in the cache, the oldest entries are evicted to meet the new capacity. The capacity_ member is no longer const. New tests are added to verify the behavior of UpdateMaxSize and insertions with different cache capacities, including a zero capacity, which is explicitly supported as a way to disable the cache. This will be used in Chromium to reduce the capacity of a cache when memory pressure is detected. This is a no-op change to production code if the new method is not called. PiperOrigin-RevId: 855929998
1 parent 49eae60 commit 649bff3

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

quiche/quic/core/quic_lru_cache.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ class QUICHE_EXPORT QuicLRUCache {
8282
// Removes all entries from the cache.
8383
void Clear() { cache_.clear(); }
8484

85+
// Update the maximum size of the cache. If new capacity is smaller than
86+
// current size, evicts the oldest entries.
87+
void UpdateMaxSize(size_t capacity) {
88+
capacity_ = capacity;
89+
while (cache_.size() > capacity_) {
90+
cache_.pop_front();
91+
}
92+
}
93+
8594
// Returns maximum size of the cache.
8695
size_t MaxSize() const { return capacity_; }
8796

@@ -90,7 +99,7 @@ class QUICHE_EXPORT QuicLRUCache {
9099

91100
private:
92101
quiche::QuicheLinkedHashMap<K, std::unique_ptr<V>, Hash, Eq> cache_;
93-
const size_t capacity_;
102+
size_t capacity_;
94103
};
95104

96105
} // namespace quic

quiche/quic/core/quic_lru_cache_test.cc

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,18 @@ TEST(QuicLRUCacheTest, InsertAndLookup) {
2626
EXPECT_EQ(5u, cache.MaxSize());
2727

2828
// Check that item 1 was properly inserted.
29-
std::unique_ptr<CachedItem> item1(new CachedItem(11));
29+
auto item1 = std::make_unique<CachedItem>(11);
3030
cache.Insert(1, std::move(item1));
3131
EXPECT_EQ(1u, cache.Size());
3232
EXPECT_EQ(11u, cache.Lookup(1)->second->value);
3333

3434
// Check that item 2 overrides item 1.
35-
std::unique_ptr<CachedItem> item2(new CachedItem(12));
35+
auto item2 = std::make_unique<CachedItem>(12);
3636
cache.Insert(1, std::move(item2));
3737
EXPECT_EQ(1u, cache.Size());
3838
EXPECT_EQ(12u, cache.Lookup(1)->second->value);
3939

40-
std::unique_ptr<CachedItem> item3(new CachedItem(13));
40+
auto item3 = std::make_unique<CachedItem>(13);
4141
cache.Insert(3, std::move(item3));
4242
EXPECT_EQ(2u, cache.Size());
4343
auto iter = cache.Lookup(3);
@@ -56,7 +56,7 @@ TEST(QuicLRUCacheTest, Eviction) {
5656
QuicLRUCache<int, CachedItem> cache(3);
5757

5858
for (size_t i = 1; i <= 4; ++i) {
59-
std::unique_ptr<CachedItem> item(new CachedItem(10 + i));
59+
auto item = std::make_unique<CachedItem>(10 + i);
6060
cache.Insert(i, std::move(item));
6161
}
6262

@@ -68,7 +68,7 @@ TEST(QuicLRUCacheTest, Eviction) {
6868
EXPECT_EQ(14u, cache.Lookup(4)->second->value);
6969

7070
EXPECT_EQ(12u, cache.Lookup(2)->second->value);
71-
std::unique_ptr<CachedItem> item5(new CachedItem(15));
71+
auto item5 = std::make_unique<CachedItem>(15);
7272
cache.Insert(5, std::move(item5));
7373
// Make sure item 3 is evicted.
7474
EXPECT_EQ(cache.end(), cache.Lookup(3));
@@ -79,6 +79,73 @@ TEST(QuicLRUCacheTest, Eviction) {
7979
EXPECT_EQ(0u, cache.Size());
8080
}
8181

82+
TEST(QuicLRUCacheTest, UpdateMaxSize) {
83+
QuicLRUCache<int, CachedItem> cache(3);
84+
85+
// Insert 3 items, filling the cache.
86+
for (size_t i = 1; i <= 3; ++i) {
87+
auto item = std::make_unique<CachedItem>(10 + i);
88+
cache.Insert(i, std::move(item));
89+
}
90+
EXPECT_EQ(3u, cache.Size());
91+
EXPECT_EQ(3u, cache.MaxSize());
92+
93+
// Update max size to a larger value.
94+
cache.UpdateMaxSize(5);
95+
EXPECT_EQ(3u, cache.Size());
96+
EXPECT_EQ(5u, cache.MaxSize());
97+
98+
// Insert more items, up to the new max size.
99+
for (size_t i = 4; i <= 5; ++i) {
100+
auto item = std::make_unique<CachedItem>(10 + i);
101+
cache.Insert(i, std::move(item));
102+
}
103+
EXPECT_EQ(5u, cache.Size());
104+
EXPECT_EQ(5u, cache.MaxSize());
105+
106+
// Update max size to a smaller value, causing evictions.
107+
cache.UpdateMaxSize(2);
108+
EXPECT_EQ(2u, cache.Size());
109+
EXPECT_EQ(2u, cache.MaxSize());
110+
// Items 1, 2, and 3 should be evicted.
111+
EXPECT_EQ(cache.end(), cache.Lookup(1));
112+
EXPECT_EQ(cache.end(), cache.Lookup(2));
113+
EXPECT_EQ(cache.end(), cache.Lookup(3));
114+
// Items 4 and 5 should remain.
115+
EXPECT_NE(cache.end(), cache.Lookup(4));
116+
EXPECT_NE(cache.end(), cache.Lookup(5));
117+
118+
// Insert an item after reducing max size to 2. This should evict item 4.
119+
auto item6 = std::make_unique<CachedItem>(16);
120+
cache.Insert(6, std::move(item6));
121+
EXPECT_EQ(2u, cache.Size());
122+
EXPECT_EQ(cache.end(), cache.Lookup(4));
123+
EXPECT_NE(cache.end(), cache.Lookup(5));
124+
EXPECT_NE(cache.end(), cache.Lookup(6));
125+
126+
// Update max size to 0.
127+
cache.UpdateMaxSize(0);
128+
EXPECT_EQ(0u, cache.Size());
129+
EXPECT_EQ(0u, cache.MaxSize());
130+
EXPECT_EQ(cache.end(), cache.Lookup(5));
131+
EXPECT_EQ(cache.end(), cache.Lookup(6));
132+
}
133+
134+
TEST(QuicLRUCacheTest, InsertWithZeroMaxSize) {
135+
QuicLRUCache<int, CachedItem> cache(0);
136+
EXPECT_EQ(0u, cache.Size());
137+
EXPECT_EQ(0u, cache.MaxSize());
138+
139+
// Attempt to insert an item.
140+
auto item1 = std::make_unique<CachedItem>(1);
141+
cache.Insert(1, std::move(item1));
142+
143+
// The cache should still be empty.
144+
EXPECT_EQ(0u, cache.Size());
145+
EXPECT_EQ(0u, cache.MaxSize());
146+
EXPECT_EQ(cache.end(), cache.Lookup(1));
147+
}
148+
82149
} // namespace
83150
} // namespace test
84151
} // namespace quic

0 commit comments

Comments
 (0)