Coverage Report

Created: 2025-03-08 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/nativelink-util/src/evicting_map.rs
Line
Count
Source
1
// Copyright 2024 The NativeLink Authors. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use std::borrow::Borrow;
16
use std::cmp::Eq;
17
use std::collections::BTreeSet;
18
use std::fmt::Debug;
19
use std::future::Future;
20
use std::hash::Hash;
21
use std::ops::RangeBounds;
22
use std::sync::Arc;
23
24
use async_lock::Mutex;
25
use lru::LruCache;
26
use nativelink_config::stores::EvictionPolicy;
27
use nativelink_metric::MetricsComponent;
28
use serde::{Deserialize, Serialize};
29
use tracing::{event, Level};
30
31
use crate::instant_wrapper::InstantWrapper;
32
use crate::metrics_utils::{Counter, CounterWithTime};
33
34
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
35
pub struct SerializedLRU<K> {
36
    pub data: Vec<(K, i32)>,
37
    pub anchor_time: u64,
38
}
39
40
#[derive(Debug)]
41
struct EvictionItem<T: LenEntry + Debug> {
42
    seconds_since_anchor: i32,
43
    data: T,
44
}
45
46
pub trait LenEntry: 'static {
47
    /// Length of referenced data.
48
    fn len(&self) -> u64;
49
50
    /// Returns `true` if `self` has zero length.
51
    fn is_empty(&self) -> bool;
52
53
    /// This will be called when object is removed from map.
54
    /// Note: There may still be a reference to it held somewhere else, which
55
    /// is why it can't be mutable. This is a good place to mark the item
56
    /// to be deleted and then in the Drop call actually do the deleting.
57
    /// This will ensure nowhere else in the program still holds a reference
58
    /// to this object.
59
    /// You should not rely only on the Drop trait. Doing so might result in the
60
    /// program safely shutting down and calling the Drop method on each object,
61
    /// which if you are deleting items you may not want to do.
62
    /// It is undefined behavior to have `unref()` called more than once.
63
    /// During the execution of `unref()` no items can be added or removed to/from
64
    /// the `EvictionMap` globally (including inside `unref()`).
65
    #[inline]
66
46
    fn unref(&self) -> impl Future<Output = ()> + Send {
67
46
        std::future::ready(())
68
46
    }
69
}
70
71
impl<T: LenEntry + Send + Sync> LenEntry for Arc<T> {
72
    #[inline]
73
276
    fn len(&self) -> u64 {
74
276
        T::len(self.as_ref())
75
276
    }
76
77
    #[inline]
78
0
    fn is_empty(&self) -> bool {
79
0
        T::is_empty(self.as_ref())
80
0
    }
81
82
    #[inline]
83
30
    async fn unref(&self) {
84
30
        self.as_ref().unref().await;
85
30
    }
86
}
87
88
#[derive(MetricsComponent)]
89
struct State<K: Ord + Hash + Eq + Clone + Debug + Send, T: LenEntry + Debug + Send> {
90
    lru: LruCache<K, EvictionItem<T>>,
91
    btree: Option<BTreeSet<K>>,
92
    #[metric(help = "Total size of all items in the store")]
93
    sum_store_size: u64,
94
95
    #[metric(help = "Number of bytes evicted from the store")]
96
    evicted_bytes: Counter,
97
    #[metric(help = "Number of items evicted from the store")]
98
    evicted_items: CounterWithTime,
99
    #[metric(help = "Number of bytes replaced in the store")]
100
    replaced_bytes: Counter,
101
    #[metric(help = "Number of items replaced in the store")]
102
    replaced_items: CounterWithTime,
103
    #[metric(help = "Number of bytes inserted into the store since it was created")]
104
    lifetime_inserted_bytes: Counter,
105
}
106
107
impl<K: Ord + Hash + Eq + Clone + Debug + Send + Sync, T: LenEntry + Debug + Sync + Send>
108
    State<K, T>
109
{
110
    /// Removes an item from the cache.
111
75
    async fn remove<Q>(&mut self, key: &Q, eviction_item: &EvictionItem<T>, replaced: bool)
112
75
    where
113
75
        K: Borrow<Q>,
114
75
        Q: Ord + Hash + Eq + Debug + Sync,
115
75
    {
116
75
        if let Some(
btree0
) = &mut self.btree {
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 21]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [Folded - Ignored]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 6]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 14]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 2]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 1]
  Branch (116:16): [True: 0, False: 3]
  Branch (116:16): [True: 0, False: 2]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [Folded - Ignored]
  Branch (116:16): [True: 0, False: 18]
  Branch (116:16): [True: 0, False: 0]
  Branch (116:16): [True: 0, False: 1]
117
0
            btree.remove(key.borrow());
118
75
        }
119
75
        self.sum_store_size -= eviction_item.data.len();
120
75
        if replaced {
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 20, False: 1]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [Folded - Ignored]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 6]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 1]
  Branch (120:12): [True: 1, False: 0]
  Branch (120:12): [True: 0, False: 14]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 1]
  Branch (120:12): [True: 0, False: 2]
  Branch (120:12): [True: 0, False: 1]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 1]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 1, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 1, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 1]
  Branch (120:12): [True: 3, False: 0]
  Branch (120:12): [True: 0, False: 2]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [Folded - Ignored]
  Branch (120:12): [True: 18, False: 0]
  Branch (120:12): [True: 0, False: 0]
  Branch (120:12): [True: 0, False: 1]
121
44
            self.replaced_items.inc();
122
44
            self.replaced_bytes.add(eviction_item.data.len());
123
44
        } else {
124
31
            self.evicted_items.inc();
125
31
            self.evicted_bytes.add(eviction_item.data.len());
126
31
        }
127
        // Note: See comment in `unref()` requring global lock of insert/remove.
128
75
        eviction_item.data.unref().await;
129
75
    }
130
131
    /// Inserts a new item into the cache. If the key already exists, the old item is returned.
132
5.92k
    async fn put(&mut self, key: K, eviction_item: EvictionItem<T>) -> Option<T> {
133
        // If we are maintaining a btree index, we need to update it.
134
5.92k
        if let Some(
btree0
) = &mut self.btree {
  Branch (134:16): [True: 0, False: 0]
  Branch (134:16): [True: 0, False: 5.74k]
  Branch (134:16): [True: 0, False: 0]
  Branch (134:16): [True: 0, False: 0]
  Branch (134:16): [Folded - Ignored]
  Branch (134:16): [True: 0, False: 2]
  Branch (134:16): [True: 0, False: 27]
  Branch (134:16): [True: 0, False: 3]
  Branch (134:16): [True: 0, False: 5]
  Branch (134:16): [True: 0, False: 2]
  Branch (134:16): [True: 0, False: 2]
  Branch (134:16): [True: 0, False: 2]
  Branch (134:16): [True: 0, False: 2]
  Branch (134:16): [True: 0, False: 1]
  Branch (134:16): [True: 0, False: 16]
  Branch (134:16): [True: 0, False: 0]
  Branch (134:16): [Folded - Ignored]
  Branch (134:16): [True: 0, False: 93]
  Branch (134:16): [True: 0, False: 27]
135
0
            btree.insert(key.clone());
136
5.92k
        }
137
5.92k
        if let Some(
old_item44
) = self.lru.put(key.clone(), eviction_item) {
  Branch (137:16): [True: 0, False: 0]
  Branch (137:16): [True: 20, False: 5.72k]
  Branch (137:16): [True: 0, False: 0]
  Branch (137:16): [True: 0, False: 0]
  Branch (137:16): [Folded - Ignored]
  Branch (137:16): [True: 1, False: 1]
  Branch (137:16): [True: 0, False: 27]
  Branch (137:16): [True: 0, False: 3]
  Branch (137:16): [True: 0, False: 5]
  Branch (137:16): [True: 0, False: 2]
  Branch (137:16): [True: 0, False: 2]
  Branch (137:16): [True: 1, False: 1]
  Branch (137:16): [True: 1, False: 1]
  Branch (137:16): [True: 0, False: 1]
  Branch (137:16): [True: 3, False: 13]
  Branch (137:16): [True: 0, False: 0]
  Branch (137:16): [Folded - Ignored]
  Branch (137:16): [True: 18, False: 75]
  Branch (137:16): [True: 0, False: 27]
138
44
            self.remove(&key, &old_item, true).await;
139
44
            return Some(old_item.data);
140
5.88k
        }
141
5.88k
        None
142
5.92k
    }
143
}
144
145
#[derive(MetricsComponent)]
146
pub struct EvictingMap<
147
    K: Ord + Hash + Eq + Clone + Debug + Send,
148
    T: LenEntry + Debug + Send,
149
    I: InstantWrapper,
150
> {
151
    #[metric]
152
    state: Mutex<State<K, T>>,
153
    anchor_time: I,
154
    #[metric(help = "Maximum size of the store in bytes")]
155
    max_bytes: u64,
156
    #[metric(help = "Number of bytes to evict when the store is full")]
157
    evict_bytes: u64,
158
    #[metric(help = "Maximum number of seconds to keep an item in the store")]
159
    max_seconds: i32,
160
    #[metric(help = "Maximum number of items to keep in the store")]
161
    max_count: u64,
162
}
163
164
impl<K, T, I> EvictingMap<K, T, I>
165
where
166
    K: Ord + Hash + Eq + Clone + Debug + Send + Sync,
167
    T: LenEntry + Debug + Clone + Send + Sync,
168
    I: InstantWrapper,
169
{
170
390
    pub fn new(config: &EvictionPolicy, anchor_time: I) -> Self {
171
390
        EvictingMap {
172
390
            // We use unbounded because if we use the bounded version we can't call the delete
173
390
            // function on the LenEntry properly.
174
390
            state: Mutex::new(State {
175
390
                lru: LruCache::unbounded(),
176
390
                btree: None,
177
390
                sum_store_size: 0,
178
390
                evicted_bytes: Counter::default(),
179
390
                evicted_items: CounterWithTime::default(),
180
390
                replaced_bytes: Counter::default(),
181
390
                replaced_items: CounterWithTime::default(),
182
390
                lifetime_inserted_bytes: Counter::default(),
183
390
            }),
184
390
            anchor_time,
185
390
            max_bytes: config.max_bytes as u64,
186
390
            evict_bytes: config.evict_bytes as u64,
187
390
            max_seconds: config.max_seconds as i32,
188
390
            max_count: config.max_count,
189
390
        }
190
390
    }
191
192
0
    pub async fn enable_filtering(&self) {
193
0
        let mut state = self.state.lock().await;
194
0
        if state.btree.is_none() {
  Branch (194:12): [Folded - Ignored]
  Branch (194:12): [Folded - Ignored]
195
0
            Self::rebuild_btree_index(&mut state);
196
0
        }
197
0
    }
198
199
2
    fn rebuild_btree_index(state: &mut State<K, T>) {
200
6
        state.btree = Some(state.lru.iter().map(|(k, _)| k).cloned().collect());
201
2
    }
202
203
    /// Run the `handler` function on each key-value pair that matches the `prefix_range`
204
    /// and return the number of items that were processed.
205
    /// The `handler` function should return `true` to continue processing the next item
206
    /// or `false` to stop processing.
207
11
    pub async fn range<F, Q>(&self, prefix_range: impl RangeBounds<Q> + Send, mut handler: F) -> u64
208
11
    where
209
11
        F: FnMut(&K, &T) -> bool + Send,
210
11
        K: Borrow<Q> + Ord,
211
11
        Q: Ord + Hash + Eq + Debug + Sync,
212
11
    {
213
11
        let mut state = self.state.lock().await;
214
11
        let btree = if let Some(
ref btree9
) = state.btree {
  Branch (214:28): [True: 6, False: 1]
  Branch (214:28): [Folded - Ignored]
  Branch (214:28): [True: 1, False: 0]
  Branch (214:28): [True: 2, False: 0]
  Branch (214:28): [True: 0, False: 1]
  Branch (214:28): [Folded - Ignored]
215
9
            btree
216
        } else {
217
2
            Self::rebuild_btree_index(&mut state);
218
2
            state.btree.as_ref().unwrap()
219
        };
220
11
        let mut continue_count = 0;
221
22
        for key in 
btree.range(prefix_range)11
{
222
22
            let value = &state.lru.peek(key.borrow()).unwrap().data;
223
22
            let should_continue = handler(key, value);
224
22
            if !should_continue {
  Branch (224:16): [True: 0, False: 13]
  Branch (224:16): [Folded - Ignored]
  Branch (224:16): [True: 0, False: 1]
  Branch (224:16): [True: 0, False: 5]
  Branch (224:16): [True: 0, False: 3]
  Branch (224:16): [Folded - Ignored]
225
0
                break;
226
22
            }
227
22
            continue_count += 1;
228
        }
229
11
        continue_count
230
11
    }
231
232
    /// Returns the number of key-value pairs that are currently in the the cache.
233
    /// Function is not for production code paths.
234
30
    pub async fn len_for_test(&self) -> usize {
235
30
        self.state.lock().await.lru.len()
236
30
    }
237
238
10.6k
    fn should_evict(
239
10.6k
        &self,
240
10.6k
        lru_len: usize,
241
10.6k
        peek_entry: &EvictionItem<T>,
242
10.6k
        sum_store_size: u64,
243
10.6k
        max_bytes: u64,
244
10.6k
    ) -> bool {
245
10.6k
        let is_over_size = max_bytes != 0 && 
sum_store_size >= max_bytes209
;
  Branch (245:28): [True: 0, False: 0]
  Branch (245:28): [True: 0, False: 0]
  Branch (245:28): [True: 100, False: 10.1k]
  Branch (245:28): [True: 0, False: 0]
  Branch (245:28): [Folded - Ignored]
  Branch (245:28): [True: 0, False: 6]
  Branch (245:28): [True: 0, False: 1]
  Branch (245:28): [True: 0, False: 3]
  Branch (245:28): [True: 30, False: 31]
  Branch (245:28): [True: 0, False: 3]
  Branch (245:28): [True: 0, False: 1]
  Branch (245:28): [True: 4, False: 1]
  Branch (245:28): [True: 3, False: 5]
  Branch (245:28): [True: 3, False: 0]
  Branch (245:28): [True: 0, False: 4]
  Branch (245:28): [True: 0, False: 2]
  Branch (245:28): [True: 0, False: 3]
  Branch (245:28): [True: 0, False: 2]
  Branch (245:28): [True: 1, False: 27]
  Branch (245:28): [True: 0, False: 0]
  Branch (245:28): [True: 0, False: 4]
  Branch (245:28): [Folded - Ignored]
  Branch (245:28): [True: 68, False: 131]
  Branch (245:28): [True: 0, False: 85]
246
247
10.6k
        let evict_older_than_seconds =
248
10.6k
            (self.anchor_time.elapsed().as_secs() as i32) - self.max_seconds;
249
10.6k
        let old_item_exists =
250
10.6k
            self.max_seconds != 0 && 
peek_entry.seconds_since_anchor < evict_older_than_seconds118
;
  Branch (250:13): [True: 0, False: 0]
  Branch (250:13): [True: 0, False: 0]
  Branch (250:13): [True: 0, False: 10.2k]
  Branch (250:13): [True: 0, False: 0]
  Branch (250:13): [Folded - Ignored]
  Branch (250:13): [True: 0, False: 6]
  Branch (250:13): [True: 0, False: 1]
  Branch (250:13): [True: 0, False: 3]
  Branch (250:13): [True: 28, False: 33]
  Branch (250:13): [True: 0, False: 3]
  Branch (250:13): [True: 0, False: 1]
  Branch (250:13): [True: 5, False: 0]
  Branch (250:13): [True: 0, False: 8]
  Branch (250:13): [True: 0, False: 3]
  Branch (250:13): [True: 0, False: 4]
  Branch (250:13): [True: 0, False: 2]
  Branch (250:13): [True: 0, False: 3]
  Branch (250:13): [True: 0, False: 2]
  Branch (250:13): [True: 0, False: 28]
  Branch (250:13): [True: 0, False: 0]
  Branch (250:13): [True: 0, False: 4]
  Branch (250:13): [Folded - Ignored]
  Branch (250:13): [True: 0, False: 199]
  Branch (250:13): [True: 85, False: 0]
251
252
10.6k
        let is_over_count = self.max_count != 0 && 
(lru_len as u64) > self.max_count20
;
  Branch (252:29): [True: 0, False: 0]
  Branch (252:29): [True: 0, False: 0]
  Branch (252:29): [True: 0, False: 10.2k]
  Branch (252:29): [True: 0, False: 0]
  Branch (252:29): [Folded - Ignored]
  Branch (252:29): [True: 0, False: 6]
  Branch (252:29): [True: 0, False: 1]
  Branch (252:29): [True: 3, False: 0]
  Branch (252:29): [True: 8, False: 53]
  Branch (252:29): [True: 0, False: 3]
  Branch (252:29): [True: 0, False: 1]
  Branch (252:29): [True: 0, False: 5]
  Branch (252:29): [True: 0, False: 8]
  Branch (252:29): [True: 0, False: 3]
  Branch (252:29): [True: 4, False: 0]
  Branch (252:29): [True: 2, False: 0]
  Branch (252:29): [True: 3, False: 0]
  Branch (252:29): [True: 0, False: 2]
  Branch (252:29): [True: 0, False: 28]
  Branch (252:29): [True: 0, False: 0]
  Branch (252:29): [True: 0, False: 4]
  Branch (252:29): [Folded - Ignored]
  Branch (252:29): [True: 0, False: 199]
  Branch (252:29): [True: 0, False: 85]
253
254
10.6k
        is_over_size || 
old_item_exists10.6k
||
is_over_count10.6k
  Branch (254:9): [True: 0, False: 0]
  Branch (254:25): [True: 0, False: 0]
  Branch (254:9): [True: 0, False: 0]
  Branch (254:25): [True: 0, False: 0]
  Branch (254:9): [True: 1, False: 10.2k]
  Branch (254:25): [True: 0, False: 10.2k]
  Branch (254:9): [True: 0, False: 0]
  Branch (254:25): [True: 0, False: 0]
  Branch (254:9): [Folded - Ignored]
  Branch (254:25): [Folded - Ignored]
  Branch (254:9): [True: 0, False: 6]
  Branch (254:25): [True: 0, False: 6]
  Branch (254:9): [True: 0, False: 1]
  Branch (254:25): [True: 0, False: 1]
  Branch (254:9): [True: 0, False: 3]
  Branch (254:25): [True: 0, False: 3]
  Branch (254:9): [True: 6, False: 55]
  Branch (254:25): [True: 7, False: 48]
  Branch (254:9): [True: 0, False: 3]
  Branch (254:25): [True: 0, False: 3]
  Branch (254:9): [True: 0, False: 1]
  Branch (254:25): [True: 0, False: 1]
  Branch (254:9): [True: 0, False: 5]
  Branch (254:25): [True: 1, False: 4]
  Branch (254:9): [True: 0, False: 8]
  Branch (254:25): [True: 0, False: 8]
  Branch (254:9): [True: 1, False: 2]
  Branch (254:25): [True: 0, False: 2]
  Branch (254:9): [True: 0, False: 4]
  Branch (254:25): [True: 0, False: 4]
  Branch (254:9): [True: 0, False: 2]
  Branch (254:25): [True: 0, False: 2]
  Branch (254:9): [True: 0, False: 3]
  Branch (254:25): [True: 0, False: 3]
  Branch (254:9): [True: 0, False: 2]
  Branch (254:25): [True: 0, False: 2]
  Branch (254:9): [True: 0, False: 28]
  Branch (254:25): [True: 0, False: 28]
  Branch (254:9): [True: 0, False: 0]
  Branch (254:25): [True: 0, False: 0]
  Branch (254:9): [True: 0, False: 4]
  Branch (254:25): [True: 0, False: 4]
  Branch (254:9): [Folded - Ignored]
  Branch (254:25): [Folded - Ignored]
  Branch (254:9): [True: 0, False: 199]
  Branch (254:25): [True: 0, False: 199]
  Branch (254:9): [True: 0, False: 85]
  Branch (254:25): [True: 1, False: 84]
255
10.6k
    }
256
257
10.4k
    async fn evict_items(&self, state: &mut State<K, T>) {
258
10.4k
        let Some((_, 
mut peek_entry10.4k
)) = state.lru.peek_lru() else {
  Branch (258:13): [True: 0, False: 0]
  Branch (258:13): [True: 10.1k, False: 4]
  Branch (258:13): [True: 0, False: 0]
  Branch (258:13): [True: 0, False: 0]
  Branch (258:13): [Folded - Ignored]
  Branch (258:13): [True: 6, False: 0]
  Branch (258:13): [True: 1, False: 0]
  Branch (258:13): [True: 3, False: 0]
  Branch (258:13): [True: 34, False: 0]
  Branch (258:13): [True: 3, False: 0]
  Branch (258:13): [True: 1, False: 0]
  Branch (258:13): [True: 1, False: 0]
  Branch (258:13): [True: 5, False: 0]
  Branch (258:13): [True: 2, False: 0]
  Branch (258:13): [True: 3, False: 0]
  Branch (258:13): [True: 2, False: 0]
  Branch (258:13): [True: 3, False: 0]
  Branch (258:13): [True: 2, False: 0]
  Branch (258:13): [True: 27, False: 0]
  Branch (258:13): [True: 0, False: 0]
  Branch (258:13): [True: 4, False: 0]
  Branch (258:13): [Folded - Ignored]
  Branch (258:13): [True: 131, False: 0]
  Branch (258:13): [True: 84, False: 0]
259
4
            return;
260
        };
261
262
10.4k
        let max_bytes = if self.max_bytes != 0
  Branch (262:28): [True: 0, False: 0]
  Branch (262:28): [True: 7, False: 10.1k]
  Branch (262:28): [True: 0, False: 0]
  Branch (262:28): [True: 0, False: 0]
  Branch (262:28): [Folded - Ignored]
  Branch (262:28): [True: 0, False: 6]
  Branch (262:28): [True: 0, False: 1]
  Branch (262:28): [True: 0, False: 3]
  Branch (262:28): [True: 8, False: 26]
  Branch (262:28): [True: 0, False: 3]
  Branch (262:28): [True: 0, False: 1]
  Branch (262:28): [True: 0, False: 1]
  Branch (262:28): [True: 0, False: 5]
  Branch (262:28): [True: 2, False: 0]
  Branch (262:28): [True: 0, False: 3]
  Branch (262:28): [True: 0, False: 2]
  Branch (262:28): [True: 0, False: 3]
  Branch (262:28): [True: 0, False: 2]
  Branch (262:28): [True: 0, False: 27]
  Branch (262:28): [True: 0, False: 0]
  Branch (262:28): [True: 0, False: 4]
  Branch (262:28): [Folded - Ignored]
  Branch (262:28): [True: 0, False: 131]
  Branch (262:28): [True: 0, False: 84]
263
17
            && self.evict_bytes != 0
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 7]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [Folded - Ignored]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 4, False: 4]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 2]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [Folded - Ignored]
  Branch (263:16): [True: 0, False: 0]
  Branch (263:16): [True: 0, False: 0]
264
4
            && self.should_evict(
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [Folded - Ignored]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 1, False: 3]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [Folded - Ignored]
  Branch (264:16): [True: 0, False: 0]
  Branch (264:16): [True: 0, False: 0]
265
4
                state.lru.len(),
266
4
                peek_entry,
267
4
                state.sum_store_size,
268
4
                self.max_bytes,
269
4
            ) {
270
1
            if self.max_bytes > self.evict_bytes {
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [Folded - Ignored]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 1, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [Folded - Ignored]
  Branch (270:16): [True: 0, False: 0]
  Branch (270:16): [True: 0, False: 0]
271
1
                self.max_bytes - self.evict_bytes
272
            } else {
273
0
                0
274
            }
275
        } else {
276
10.4k
            self.max_bytes
277
        };
278
279
10.4k
        while self.should_evict(state.lru.len(), peek_entry, state.sum_store_size, max_bytes) {
  Branch (279:15): [True: 0, False: 0]
  Branch (279:15): [True: 1, False: 10.1k]
  Branch (279:15): [True: 0, False: 0]
  Branch (279:15): [True: 0, False: 0]
  Branch (279:15): [Folded - Ignored]
  Branch (279:15): [True: 0, False: 6]
  Branch (279:15): [True: 0, False: 1]
  Branch (279:15): [True: 0, False: 3]
  Branch (279:15): [True: 12, False: 31]
  Branch (279:15): [True: 0, False: 3]
  Branch (279:15): [True: 0, False: 1]
  Branch (279:15): [True: 0, False: 1]
  Branch (279:15): [True: 0, False: 5]
  Branch (279:15): [True: 1, False: 2]
  Branch (279:15): [True: 1, False: 3]
  Branch (279:15): [True: 0, False: 2]
  Branch (279:15): [True: 0, False: 3]
  Branch (279:15): [True: 0, False: 2]
  Branch (279:15): [True: 0, False: 27]
  Branch (279:15): [True: 0, False: 0]
  Branch (279:15): [True: 0, False: 4]
  Branch (279:15): [Folded - Ignored]
  Branch (279:15): [True: 0, False: 131]
  Branch (279:15): [True: 1, False: 84]
280
16
            let (key, eviction_item) = state
281
16
                .lru
282
16
                .pop_lru()
283
16
                .expect("Tried to peek() then pop() but failed");
284
16
            event!(Level::INFO, ?key, 
"Evicting"0
,);
285
16
            state.remove(&key, &eviction_item, false).await;
286
287
16
            peek_entry = if let Some((_, 
entry13
)) = state.lru.peek_lru() {
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 1, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [Folded - Ignored]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 9, False: 3]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 1, False: 0]
  Branch (287:33): [True: 1, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [Folded - Ignored]
  Branch (287:33): [True: 0, False: 0]
  Branch (287:33): [True: 1, False: 0]
288
13
                entry
289
            } else {
290
3
                return;
291
            };
292
        }
293
10.4k
    }
294
295
    /// Return the size of a `key`, if not found `None` is returned.
296
25
    pub async fn size_for_key<Q>(&self, key: &Q) -> Option<u64>
297
25
    where
298
25
        K: Borrow<Q>,
299
25
        Q: Ord + Hash + Eq + Debug + Sync,
300
25
    {
301
25
        let mut results = [None];
302
25
        self.sizes_for_keys([key], &mut results[..], false).await;
303
25
        results[0]
304
25
    }
305
306
    /// Return the sizes of a collection of `keys`. Expects `results` collection
307
    /// to be provided for storing the resulting key sizes. Each index value in
308
    /// `keys` maps directly to the size value for the key in `results`.
309
    /// If no key is found in the internal map, `None` is filled in its place.
310
    /// If `peek` is set to `true`, the items are not promoted to the front of the
311
    /// LRU cache. Note: peek may still evict, but won't promote.
312
290
    pub async fn sizes_for_keys<It, Q, R>(&self, keys: It, results: &mut [Option<u64>], peek: bool)
313
290
    where
314
290
        It: IntoIterator<Item = R> + Send,
315
290
        // Note: It's not enough to have the inserts themselves be Send. The
316
290
        // returned iterator should be Send as well.
317
290
        <It as IntoIterator>::IntoIter: Send,
318
290
        // This may look strange, but what we are doing is saying:
319
290
        // * `K` must be able to borrow `Q`
320
290
        // * `R` (the input stream item type) must also be able to borrow `Q`
321
290
        // Note: That K and R do not need to be the same type, they just both need
322
290
        // to be able to borrow a `Q`.
323
290
        K: Borrow<Q>,
324
290
        R: Borrow<Q> + Send,
325
290
        Q: Ord + Hash + Eq + Debug + Sync,
326
290
    {
327
290
        let mut state = self.state.lock().await;
328
329
290
        let lru_len = state.lru.len();
330
325
        for (key, result) in 
keys.into_iter().zip(results.iter_mut())290
{
331
325
            let maybe_entry = if peek {
  Branch (331:34): [True: 0, False: 0]
  Branch (331:34): [True: 0, False: 203]
  Branch (331:34): [True: 0, False: 0]
  Branch (331:34): [Folded - Ignored]
  Branch (331:34): [True: 0, False: 25]
  Branch (331:34): [True: 5, False: 0]
  Branch (331:34): [True: 3, False: 0]
  Branch (331:34): [True: 4, False: 0]
  Branch (331:34): [True: 0, False: 0]
  Branch (331:34): [True: 0, False: 0]
  Branch (331:34): [True: 0, False: 0]
  Branch (331:34): [True: 0, False: 0]
  Branch (331:34): [True: 0, False: 1]
  Branch (331:34): [True: 0, False: 3]
  Branch (331:34): [True: 0, False: 0]
  Branch (331:34): [Folded - Ignored]
  Branch (331:34): [True: 0, False: 81]
332
12
                state.lru.peek_mut(key.borrow())
333
            } else {
334
313
                state.lru.get_mut(key.borrow())
335
            };
336
325
            match maybe_entry {
337
182
                Some(entry) => {
338
182
                    // Note: We need to check eviction because the item might be expired
339
182
                    // based on the current time. In such case, we remove the item while
340
182
                    // we are here.
341
182
                    if self.should_evict(lru_len, entry, 0, u64::MAX) {
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [True: 0, False: 92]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [Folded - Ignored]
  Branch (341:24): [True: 1, False: 13]
  Branch (341:24): [True: 1, False: 3]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [True: 0, False: 3]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [True: 0, False: 1]
  Branch (341:24): [True: 0, False: 0]
  Branch (341:24): [Folded - Ignored]
  Branch (341:24): [True: 0, False: 68]
342
2
                        *result = None;
343
2
                        if let Some((key, eviction_item)) = state.lru.pop_entry(key.borrow()) {
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [Folded - Ignored]
  Branch (343:32): [True: 1, False: 0]
  Branch (343:32): [True: 1, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [True: 0, False: 0]
  Branch (343:32): [Folded - Ignored]
  Branch (343:32): [True: 0, False: 0]
344
2
                            event!(Level::INFO, ?key, 
"Item expired, evicting"0
);
345
2
                            state.remove(key.borrow(), &eviction_item, false).await;
346
0
                        }
347
                    } else {
348
180
                        if !peek {
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [True: 92, False: 0]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [Folded - Ignored]
  Branch (348:28): [True: 13, False: 0]
  Branch (348:28): [True: 0, False: 3]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [True: 0, False: 3]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [True: 1, False: 0]
  Branch (348:28): [True: 0, False: 0]
  Branch (348:28): [Folded - Ignored]
  Branch (348:28): [True: 68, False: 0]
349
174
                            entry.seconds_since_anchor =
350
174
                                self.anchor_time.elapsed().as_secs() as i32;
351
174
                        
}6
352
180
                        *result = Some(entry.data.len());
353
                    }
354
                }
355
143
                None => *result = None,
356
            }
357
        }
358
290
    }
359
360
4.48k
    pub async fn get<Q>(&self, key: &Q) -> Option<T>
361
4.48k
    where
362
4.48k
        K: Borrow<Q>,
363
4.48k
        Q: Ord + Hash + Eq + Debug + Sync,
364
4.48k
    {
365
4.48k
        let mut state = self.state.lock().await;
366
4.48k
        self.evict_items(&mut *state).await;
367
368
4.48k
        let 
entry4.47k
= state.lru.get_mut(key.borrow())
?9
;
369
370
4.47k
        entry.seconds_since_anchor = self.anchor_time.elapsed().as_secs() as i32;
371
4.47k
        Some(entry.data.clone())
372
4.48k
    }
373
374
    /// Returns the replaced item if any.
375
5.92k
    pub async fn insert(&self, key: K, data: T) -> Option<T> {
376
5.92k
        self.insert_with_time(key, data, self.anchor_time.elapsed().as_secs() as i32)
377
5.92k
            .await
378
5.92k
    }
379
380
    /// Returns the replaced item if any.
381
5.92k
    pub async fn insert_with_time(&self, key: K, data: T, seconds_since_anchor: i32) -> Option<T> {
382
5.92k
        let mut state = self.state.lock().await;
383
5.92k
        let results = self
384
5.92k
            .inner_insert_many(&mut state, [(key, data)], seconds_since_anchor)
385
5.92k
            .await;
386
5.92k
        results.into_iter().next()
387
5.92k
    }
388
389
    /// Same as `insert()`, but optimized for multiple inserts.
390
    /// Returns the replaced items if any.
391
5
    pub async fn insert_many<It>(&self, inserts: It) -> Vec<T>
392
5
    where
393
5
        It: IntoIterator<Item = (K, T)> + Send,
394
5
        // Note: It's not enough to have the inserts themselves be Send. The
395
5
        // returned iterator should be Send as well.
396
5
        <It as IntoIterator>::IntoIter: Send,
397
5
    {
398
5
        let mut inserts = inserts.into_iter().peekable();
399
5
        // Shortcut for cases where there are no inserts, so we don't need to lock.
400
5
        if inserts.peek().is_none() {
  Branch (400:12): [True: 0, False: 0]
  Branch (400:12): [Folded - Ignored]
  Branch (400:12): [True: 1, False: 1]
  Branch (400:12): [True: 2, False: 1]
  Branch (400:12): [Folded - Ignored]
401
3
            return Vec::new();
402
2
        }
403
2
        let state = &mut self.state.lock().await;
404
2
        self.inner_insert_many(state, inserts, self.anchor_time.elapsed().as_secs() as i32)
405
2
            .await
406
5
    }
407
408
5.92k
    async fn inner_insert_many<It>(
409
5.92k
        &self,
410
5.92k
        state: &mut State<K, T>,
411
5.92k
        inserts: It,
412
5.92k
        seconds_since_anchor: i32,
413
5.92k
    ) -> Vec<T>
414
5.92k
    where
415
5.92k
        It: IntoIterator<Item = (K, T)> + Send,
416
5.92k
        // Note: It's not enough to have the inserts themselves be Send. The
417
5.92k
        // returned iterator should be Send as well.
418
5.92k
        <It as IntoIterator>::IntoIter: Send,
419
5.92k
    {
420
5.92k
        let mut replaced_items = Vec::new();
421
11.8k
        for (
key, data5.92k
) in inserts {
422
5.92k
            let new_item_size = data.len();
423
5.92k
            let eviction_item = EvictionItem {
424
5.92k
                seconds_since_anchor,
425
5.92k
                data,
426
5.92k
            };
427
428
5.92k
            if let Some(
old_item44
) = state.put(key, eviction_item).await {
  Branch (428:20): [True: 0, False: 0]
  Branch (428:20): [True: 20, False: 5.72k]
  Branch (428:20): [True: 0, False: 0]
  Branch (428:20): [True: 0, False: 0]
  Branch (428:20): [True: 0, False: 0]
  Branch (428:20): [Folded - Ignored]
  Branch (428:20): [True: 1, False: 1]
  Branch (428:20): [True: 0, False: 27]
  Branch (428:20): [True: 0, False: 3]
  Branch (428:20): [True: 0, False: 0]
  Branch (428:20): [True: 0, False: 1]
  Branch (428:20): [True: 0, False: 3]
  Branch (428:20): [True: 0, False: 1]
  Branch (428:20): [True: 0, False: 2]
  Branch (428:20): [True: 0, False: 2]
  Branch (428:20): [True: 1, False: 1]
  Branch (428:20): [True: 1, False: 1]
  Branch (428:20): [True: 0, False: 1]
  Branch (428:20): [True: 3, False: 13]
  Branch (428:20): [True: 0, False: 0]
  Branch (428:20): [Folded - Ignored]
  Branch (428:20): [True: 18, False: 75]
  Branch (428:20): [True: 0, False: 27]
429
44
                replaced_items.push(old_item);
430
5.88k
            }
431
5.92k
            state.sum_store_size += new_item_size;
432
5.92k
            state.lifetime_inserted_bytes.add(new_item_size);
433
5.92k
            self.evict_items(state).await;
434
        }
435
5.92k
        replaced_items
436
5.92k
    }
437
438
13
    pub async fn remove<Q>(&self, key: &Q) -> bool
439
13
    where
440
13
        K: Borrow<Q>,
441
13
        Q: Ord + Hash + Eq + Debug + Sync,
442
13
    {
443
13
        let mut state = self.state.lock().await;
444
13
        self.inner_remove(&mut state, key).await
445
13
    }
446
447
14
    async fn inner_remove<Q>(&self, state: &mut State<K, T>, key: &Q) -> bool
448
14
    where
449
14
        K: Borrow<Q>,
450
14
        Q: Ord + Hash + Eq + Debug + Sync,
451
14
    {
452
14
        self.evict_items(state).await;
453
14
        if let Some(
entry13
) = state.lru.pop(key.borrow()) {
  Branch (453:16): [True: 0, False: 0]
  Branch (453:16): [Folded - Ignored]
  Branch (453:16): [True: 6, False: 0]
  Branch (453:16): [True: 1, False: 0]
  Branch (453:16): [True: 1, False: 1]
  Branch (453:16): [True: 1, False: 0]
  Branch (453:16): [True: 1, False: 0]
  Branch (453:16): [True: 0, False: 0]
  Branch (453:16): [True: 0, False: 0]
  Branch (453:16): [True: 0, False: 0]
  Branch (453:16): [True: 0, False: 0]
  Branch (453:16): [True: 1, False: 0]
  Branch (453:16): [True: 2, False: 0]
  Branch (453:16): [True: 0, False: 0]
  Branch (453:16): [Folded - Ignored]
  Branch (453:16): [True: 0, False: 0]
454
13
            state.remove(key, &entry, false).await;
455
13
            return true;
456
1
        }
457
1
        false
458
14
    }
459
460
    /// Same as `remove()`, but allows for a conditional to be applied to the
461
    /// entry before removal in an atomic fashion.
462
1
    pub async fn remove_if<Q, F>(&self, key: &Q, cond: F) -> bool
463
1
    where
464
1
        K: Borrow<Q>,
465
1
        Q: Ord + Hash + Eq + Debug + Sync,
466
1
        F: FnOnce(&T) -> bool + Send,
467
1
    {
468
1
        let mut state = self.state.lock().await;
469
1
        if let Some(entry) = state.lru.get(key.borrow()) {
  Branch (469:16): [True: 0, False: 0]
  Branch (469:16): [Folded - Ignored]
  Branch (469:16): [True: 0, False: 0]
  Branch (469:16): [True: 0, False: 0]
  Branch (469:16): [True: 0, False: 0]
  Branch (469:16): [True: 0, False: 0]
  Branch (469:16): [True: 1, False: 0]
  Branch (469:16): [True: 0, False: 0]
  Branch (469:16): [True: 0, False: 0]
  Branch (469:16): [Folded - Ignored]
  Branch (469:16): [True: 0, False: 0]
470
1
            if !cond(&entry.data) {
  Branch (470:16): [True: 0, False: 0]
  Branch (470:16): [Folded - Ignored]
  Branch (470:16): [True: 0, False: 0]
  Branch (470:16): [True: 0, False: 0]
  Branch (470:16): [True: 0, False: 0]
  Branch (470:16): [True: 0, False: 0]
  Branch (470:16): [True: 0, False: 1]
  Branch (470:16): [True: 0, False: 0]
  Branch (470:16): [True: 0, False: 0]
  Branch (470:16): [Folded - Ignored]
  Branch (470:16): [True: 0, False: 0]
471
0
                return false;
472
1
            }
473
1
            return self.inner_remove(&mut state, key).await;
474
0
        }
475
0
        false
476
1
    }
477
}