Skip to content

Commit 210aede

Browse files
Correct the LRU cache functionality. (#3736)
## Motivation The LRU cache is defined as "Least Recently Used", that is that the last unused entry gets removed. The code did not implement this idea. ## Proposal We correct the LRU so that access to a cache entry leads to a change in the position. ## Test Plan The CI. ## Release Plan Normal release. ## Links None.
1 parent e6c5754 commit 210aede

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

linera-views/src/backends/lru_caching.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,7 @@ impl LruPrefixCache {
153153
btree_map::Entry::Occupied(mut entry) => {
154154
entry.insert(cache_entry);
155155
// Put it on first position for LRU
156-
let Some(old_key_value_size) = self.queue.remove(&key) else {
157-
unreachable!("The entry should be present in the queue");
158-
};
156+
let old_key_value_size = self.queue.remove(&key).expect("old_key_value_size");
159157
self.total_size -= old_key_value_size;
160158
self.queue.insert(key, key_value_size);
161159
self.total_size += key_value_size;
@@ -215,23 +213,36 @@ impl LruPrefixCache {
215213
/// Returns the cached value, or `Some(None)` if the entry does not exist in the
216214
/// database. If `None` is returned, the entry might exist in the database but is
217215
/// not in the cache.
218-
pub fn query_read_value(&self, key: &[u8]) -> Option<Option<Vec<u8>>> {
219-
match self.map.get(key) {
216+
pub fn query_read_value(&mut self, key: &[u8]) -> Option<Option<Vec<u8>>> {
217+
let result = match self.map.get(key) {
220218
None => None,
221219
Some(entry) => match entry {
222220
CacheEntry::DoesNotExist => Some(None),
223221
CacheEntry::Exists => None,
224222
CacheEntry::Value(vec) => Some(Some(vec.clone())),
225223
},
224+
};
225+
if result.is_some() {
226+
// Put back the key on top
227+
let key_value_size = self.queue.remove(key).expect("key_value_size");
228+
self.queue.insert(key.to_vec(), key_value_size);
226229
}
230+
result
227231
}
228232

229233
/// Returns `Some(true)` or `Some(false)` if we know that the entry does or does not
230234
/// exist in the database. Returns `None` if that information is not in the cache.
231-
pub fn query_contains_key(&self, key: &[u8]) -> Option<bool> {
232-
self.map
235+
pub fn query_contains_key(&mut self, key: &[u8]) -> Option<bool> {
236+
let result = self
237+
.map
233238
.get(key)
234-
.map(|entry| !matches!(entry, CacheEntry::DoesNotExist))
239+
.map(|entry| !matches!(entry, CacheEntry::DoesNotExist));
240+
if result.is_some() {
241+
// Put back the key on top
242+
let key_value_size = self.queue.remove(key).expect("key_value_size");
243+
self.queue.insert(key.to_vec(), key_value_size);
244+
}
245+
result
235246
}
236247
}
237248

@@ -270,7 +281,7 @@ where
270281
};
271282
// First inquiring in the read_value_bytes LRU
272283
{
273-
let cache = cache.lock().unwrap();
284+
let mut cache = cache.lock().unwrap();
274285
if let Some(value) = cache.query_read_value(key) {
275286
#[cfg(with_metrics)]
276287
READ_VALUE_CACHE_HIT_COUNT.with_label_values(&[]).inc();
@@ -290,7 +301,7 @@ where
290301
return self.store.contains_key(key).await;
291302
};
292303
{
293-
let cache = cache.lock().unwrap();
304+
let mut cache = cache.lock().unwrap();
294305
if let Some(value) = cache.query_contains_key(key) {
295306
#[cfg(with_metrics)]
296307
CONTAINS_KEY_CACHE_HIT_COUNT.with_label_values(&[]).inc();
@@ -314,7 +325,7 @@ where
314325
let mut indices = Vec::new();
315326
let mut key_requests = Vec::new();
316327
{
317-
let cache = cache.lock().unwrap();
328+
let mut cache = cache.lock().unwrap();
318329
for i in 0..size {
319330
if let Some(value) = cache.query_contains_key(&keys[i]) {
320331
#[cfg(with_metrics)]
@@ -351,7 +362,7 @@ where
351362
let mut cache_miss_indices = Vec::new();
352363
let mut miss_keys = Vec::new();
353364
{
354-
let cache = cache.lock().unwrap();
365+
let mut cache = cache.lock().unwrap();
355366
for (i, key) in keys.into_iter().enumerate() {
356367
if let Some(value) = cache.query_read_value(&key) {
357368
#[cfg(with_metrics)]

0 commit comments

Comments
 (0)