@@ -27,28 +27,64 @@ use crate::{
2727use crate :: { memory:: MemoryStore , store:: TestKeyValueStore } ;
2828
2929#[ cfg( with_metrics) ]
30- /// The total number of cache faults
31- static NUM_CACHE_FAULT : LazyLock < IntCounterVec > =
32- LazyLock :: new ( || register_int_counter_vec ( "num_cache_fault" , "Number of cache faults" , & [ ] ) ) ;
30+ /// The total number of cache read value misses
31+ static READ_VALUE_CACHE_MISS_COUNT : LazyLock < IntCounterVec > = LazyLock :: new ( || {
32+ register_int_counter_vec (
33+ "num_read_value_cache_miss" ,
34+ "Number of read value cache misses" ,
35+ & [ ] ,
36+ )
37+ } ) ;
3338
3439#[ cfg( with_metrics) ]
35- /// The total number of cache successes
36- static NUM_CACHE_SUCCESS : LazyLock < IntCounterVec > =
37- LazyLock :: new ( || register_int_counter_vec ( "num_cache_success" , "Number of cache success" , & [ ] ) ) ;
40+ /// The total number of read value cache hits
41+ static READ_VALUE_CACHE_HIT_COUNT : LazyLock < IntCounterVec > = LazyLock :: new ( || {
42+ register_int_counter_vec (
43+ "num_read_value_cache_hits" ,
44+ "Number of read value cache hits" ,
45+ & [ ] ,
46+ )
47+ } ) ;
48+
49+ #[ cfg( with_metrics) ]
50+ /// The total number of contains key cache misses
51+ static CONTAINS_KEY_CACHE_MISS_COUNT : LazyLock < IntCounterVec > = LazyLock :: new ( || {
52+ register_int_counter_vec (
53+ "num_contains_key_cache_miss" ,
54+ "Number of contains key cache misses" ,
55+ & [ ] ,
56+ )
57+ } ) ;
58+
59+ #[ cfg( with_metrics) ]
60+ /// The total number of contains key cache hits
61+ static CONTAINS_KEY_CACHE_HIT_COUNT : LazyLock < IntCounterVec > = LazyLock :: new ( || {
62+ register_int_counter_vec (
63+ "num_contains_key_cache_hit" ,
64+ "Number of contains key cache hits" ,
65+ & [ ] ,
66+ )
67+ } ) ;
68+
69+ enum CacheEntry {
70+ DoesNotExist ,
71+ Exists ,
72+ Value ( Vec < u8 > ) ,
73+ }
3874
3975/// Stores the data for simple `read_values` queries.
4076///
4177/// This data structure is inspired by the crate `lru-cache` but was modified to support
4278/// range deletions.
4379struct LruPrefixCache {
44- map : BTreeMap < Vec < u8 > , Option < Vec < u8 > > > ,
80+ map : BTreeMap < Vec < u8 > , CacheEntry > ,
4581 queue : LinkedHashMap < Vec < u8 > , ( ) , RandomState > ,
4682 max_cache_size : usize ,
4783 /// Whether we have exclusive R/W access to the keys under the root key of the store.
4884 has_exclusive_access : bool ,
4985}
5086
51- impl < ' a > LruPrefixCache {
87+ impl LruPrefixCache {
5288 /// Creates an `LruPrefixCache`.
5389 pub fn new ( max_cache_size : usize ) -> Self {
5490 Self {
@@ -60,39 +96,57 @@ impl<'a> LruPrefixCache {
6096 }
6197
6298 /// Inserts an entry into the cache.
63- pub fn insert ( & mut self , key : Vec < u8 > , value : Option < Vec < u8 > > ) {
64- if value . is_none ( ) && !self . has_exclusive_access {
99+ pub fn insert ( & mut self , key : Vec < u8 > , cache_entry : CacheEntry ) {
100+ if matches ! ( cache_entry , CacheEntry :: DoesNotExist ) && !self . has_exclusive_access {
65101 // Just forget about the entry.
66102 self . map . remove ( & key) ;
67103 self . queue . remove ( & key) ;
68104 return ;
69105 }
70106 match self . map . entry ( key. clone ( ) ) {
71107 btree_map:: Entry :: Occupied ( mut entry) => {
72- entry. insert ( value ) ;
108+ entry. insert ( cache_entry ) ;
73109 // Put it on first position for LRU
74110 self . queue . remove ( & key) ;
75111 self . queue . insert ( key, ( ) ) ;
76112 }
77113 btree_map:: Entry :: Vacant ( entry) => {
78- entry. insert ( value ) ;
114+ entry. insert ( cache_entry ) ;
79115 self . queue . insert ( key, ( ) ) ;
80116 if self . queue . len ( ) > self . max_cache_size {
81- let Some ( value ) = self . queue . pop_front ( ) else {
117+ let Some ( key ) = self . queue . pop_front ( ) else {
82118 unreachable ! ( )
83119 } ;
84- self . map . remove ( & value . 0 ) ;
120+ self . map . remove ( & key . 0 ) ;
85121 }
86122 }
87123 }
88124 }
89125
126+ /// Inserts a read_value entry into the cache.
127+ pub fn insert_read_value ( & mut self , key : Vec < u8 > , value : & Option < Vec < u8 > > ) {
128+ let cache_entry = match value {
129+ None => CacheEntry :: DoesNotExist ,
130+ Some ( vec) => CacheEntry :: Value ( vec. to_vec ( ) ) ,
131+ } ;
132+ self . insert ( key, cache_entry)
133+ }
134+
135+ /// Inserts a read_value entry into the cache.
136+ pub fn insert_contains_key ( & mut self , key : Vec < u8 > , result : bool ) {
137+ let cache_entry = match result {
138+ false => CacheEntry :: DoesNotExist ,
139+ true => CacheEntry :: Exists ,
140+ } ;
141+ self . insert ( key, cache_entry)
142+ }
143+
90144 /// Marks cached keys that match the prefix as deleted. Importantly, this does not
91145 /// create new entries in the cache.
92146 pub fn delete_prefix ( & mut self , key_prefix : & [ u8 ] ) {
93147 if self . has_exclusive_access {
94148 for ( _, value) in self . map . range_mut ( get_interval ( key_prefix. to_vec ( ) ) ) {
95- * value = None ;
149+ * value = CacheEntry :: DoesNotExist ;
96150 }
97151 } else {
98152 // Just forget about the entries.
@@ -107,9 +161,26 @@ impl<'a> LruPrefixCache {
107161 }
108162 }
109163
110- /// Gets the entry from the key.
111- pub fn query ( & ' a self , key : & ' a [ u8 ] ) -> Option < & ' a Option < Vec < u8 > > > {
112- self . map . get ( key)
164+ /// Returns the cached value, or `Some(None)` if the entry does not exist in the
165+ /// database. If `None` is returned, the entry might exist in the database but is
166+ /// not in the cache.
167+ pub fn query_read_value ( & self , key : & [ u8 ] ) -> Option < Option < Vec < u8 > > > {
168+ match self . map . get ( key) {
169+ None => None ,
170+ Some ( entry) => match entry {
171+ CacheEntry :: DoesNotExist => Some ( None ) ,
172+ CacheEntry :: Exists => None ,
173+ CacheEntry :: Value ( vec) => Some ( Some ( vec. clone ( ) ) ) ,
174+ } ,
175+ }
176+ }
177+
178+ /// Returns `Some(true)` or `Some(false)` if we know that the entry does or does not
179+ /// exist in the database. Returns `None` if that information is not in the cache.
180+ pub fn query_contains_key ( & self , key : & [ u8 ] ) -> Option < bool > {
181+ self . map
182+ . get ( key)
183+ . map ( |entry| !matches ! ( entry, CacheEntry :: DoesNotExist ) )
113184 }
114185}
115186
@@ -149,28 +220,38 @@ where
149220 // First inquiring in the read_value_bytes LRU
150221 {
151222 let cache = cache. lock ( ) . unwrap ( ) ;
152- if let Some ( value) = cache. query ( key) {
223+ if let Some ( value) = cache. query_read_value ( key) {
153224 #[ cfg( with_metrics) ]
154- NUM_CACHE_SUCCESS . with_label_values ( & [ ] ) . inc ( ) ;
155- return Ok ( value. clone ( ) ) ;
225+ READ_VALUE_CACHE_HIT_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
226+ return Ok ( value) ;
156227 }
157228 }
158229 #[ cfg( with_metrics) ]
159- NUM_CACHE_FAULT . with_label_values ( & [ ] ) . inc ( ) ;
230+ READ_VALUE_CACHE_MISS_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
160231 let value = self . store . read_value_bytes ( key) . await ?;
161232 let mut cache = cache. lock ( ) . unwrap ( ) ;
162- cache. insert ( key. to_vec ( ) , value. clone ( ) ) ;
233+ cache. insert_read_value ( key. to_vec ( ) , & value) ;
163234 Ok ( value)
164235 }
165236
166237 async fn contains_key ( & self , key : & [ u8 ] ) -> Result < bool , Self :: Error > {
167- if let Some ( cache) = & self . cache {
238+ let Some ( cache) = & self . cache else {
239+ return self . store . contains_key ( key) . await ;
240+ } ;
241+ {
168242 let cache = cache. lock ( ) . unwrap ( ) ;
169- if let Some ( value) = cache. query ( key) {
170- return Ok ( value. is_some ( ) ) ;
243+ if let Some ( value) = cache. query_contains_key ( key) {
244+ #[ cfg( with_metrics) ]
245+ CONTAINS_KEY_CACHE_HIT_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
246+ return Ok ( value) ;
171247 }
172248 }
173- self . store . contains_key ( key) . await
249+ #[ cfg( with_metrics) ]
250+ CONTAINS_KEY_CACHE_MISS_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
251+ let result = self . store . contains_key ( key) . await ?;
252+ let mut cache = cache. lock ( ) . unwrap ( ) ;
253+ cache. insert_contains_key ( key. to_vec ( ) , result) ;
254+ Ok ( result)
174255 }
175256
176257 async fn contains_keys ( & self , keys : Vec < Vec < u8 > > ) -> Result < Vec < bool > , Self :: Error > {
@@ -184,18 +265,24 @@ where
184265 {
185266 let cache = cache. lock ( ) . unwrap ( ) ;
186267 for i in 0 ..size {
187- if let Some ( value) = cache. query ( & keys[ i] ) {
188- results[ i] = value. is_some ( ) ;
268+ if let Some ( value) = cache. query_contains_key ( & keys[ i] ) {
269+ #[ cfg( with_metrics) ]
270+ CONTAINS_KEY_CACHE_HIT_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
271+ results[ i] = value;
189272 } else {
273+ #[ cfg( with_metrics) ]
274+ CONTAINS_KEY_CACHE_MISS_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
190275 indices. push ( i) ;
191276 key_requests. push ( keys[ i] . clone ( ) ) ;
192277 }
193278 }
194279 }
195280 if !key_requests. is_empty ( ) {
196- let key_results = self . store . contains_keys ( key_requests) . await ?;
197- for ( index, result) in indices. into_iter ( ) . zip ( key_results) {
281+ let key_results = self . store . contains_keys ( key_requests. clone ( ) ) . await ?;
282+ let mut cache = cache. lock ( ) . unwrap ( ) ;
283+ for ( ( index, result) , key) in indices. into_iter ( ) . zip ( key_results) . zip ( key_requests) {
198284 results[ index] = result;
285+ cache. insert_contains_key ( key, result) ;
199286 }
200287 }
201288 Ok ( results)
@@ -215,13 +302,13 @@ where
215302 {
216303 let cache = cache. lock ( ) . unwrap ( ) ;
217304 for ( i, key) in keys. into_iter ( ) . enumerate ( ) {
218- if let Some ( value) = cache. query ( & key) {
305+ if let Some ( value) = cache. query_read_value ( & key) {
219306 #[ cfg( with_metrics) ]
220- NUM_CACHE_SUCCESS . with_label_values ( & [ ] ) . inc ( ) ;
221- result. push ( value. clone ( ) ) ;
307+ READ_VALUE_CACHE_HIT_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
308+ result. push ( value) ;
222309 } else {
223310 #[ cfg( with_metrics) ]
224- NUM_CACHE_FAULT . with_label_values ( & [ ] ) . inc ( ) ;
311+ READ_VALUE_CACHE_MISS_COUNT . with_label_values ( & [ ] ) . inc ( ) ;
225312 result. push ( None ) ;
226313 cache_miss_indices. push ( i) ;
227314 miss_keys. push ( key) ;
@@ -238,7 +325,7 @@ where
238325 . into_iter ( )
239326 . zip ( miss_keys. into_iter ( ) . zip ( values) )
240327 {
241- cache. insert ( key, value. clone ( ) ) ;
328+ cache. insert_read_value ( key, & value) ;
242329 result[ i] = value;
243330 }
244331 }
@@ -274,10 +361,12 @@ where
274361 for operation in & batch. operations {
275362 match operation {
276363 WriteOperation :: Put { key, value } => {
277- cache. insert ( key. to_vec ( ) , Some ( value. to_vec ( ) ) ) ;
364+ let cache_entry = CacheEntry :: Value ( value. to_vec ( ) ) ;
365+ cache. insert ( key. to_vec ( ) , cache_entry) ;
278366 }
279367 WriteOperation :: Delete { key } => {
280- cache. insert ( key. to_vec ( ) , None ) ;
368+ let cache_entry = CacheEntry :: DoesNotExist ;
369+ cache. insert ( key. to_vec ( ) , cache_entry) ;
281370 }
282371 WriteOperation :: DeletePrefix { key_prefix } => {
283372 cache. delete_prefix ( key_prefix) ;
0 commit comments