@@ -16,7 +16,7 @@ const CULL_EXEMPT_DENOMINATOR: usize = 10;
16
16
/// States that are less than or equal to this many epochs old *could* become finalized and will not
17
17
/// be culled from the cache.
18
18
const EPOCH_FINALIZATION_LIMIT : u64 = 4 ;
19
-
19
+ const RECOMPUTE_INTERVAL : usize = 10 ;
20
20
#[ derive( Debug ) ]
21
21
pub struct FinalizedState < E : EthSpec > {
22
22
state_root : Hash256 ,
@@ -48,6 +48,7 @@ pub struct StateCache<E: EthSpec> {
48
48
headroom : NonZeroUsize ,
49
49
cached_bytes : usize ,
50
50
max_cached_bytes : usize ,
51
+ put_count : usize ,
51
52
}
52
53
53
54
/// Cache of hdiff buffers for hot states.
@@ -97,6 +98,7 @@ impl<E: EthSpec> StateCache<E> {
97
98
headroom,
98
99
max_cached_bytes,
99
100
cached_bytes : 0 ,
101
+ put_count : 0 ,
100
102
}
101
103
}
102
104
@@ -249,31 +251,30 @@ impl<E: EthSpec> StateCache<E> {
249
251
// Update the cache's idea of the max epoch.
250
252
self . max_epoch = std:: cmp:: max ( state. current_epoch ( ) , self . max_epoch ) ;
251
253
252
- let state_size = state. memory_size ( ) ;
253
-
254
- // If the cache is full or would exceed the byte limit, cull states.
255
- let mut deleted_states = Vec :: new ( ) ;
256
- while self . len ( ) > 0
257
- && ( self . len ( ) >= self . capacity ( )
258
- || self . cached_bytes + state_size > self . max_cached_bytes )
259
- {
260
- deleted_states. extend ( self . cull ( self . headroom . get ( ) ) ) ;
261
- }
254
+ // If the cache is full, use the custom cull routine to make room.
255
+ let mut deleted_states =
256
+ if let Some ( over_capacity) = self . len ( ) . checked_sub ( self . capacity ( ) ) {
257
+ // The `over_capacity` should always be 0, but we add it here just in case.
258
+ self . cull ( over_capacity + self . headroom . get ( ) )
259
+ } else {
260
+ vec ! [ ]
261
+ } ;
262
262
263
263
// Insert the full state into the cache.
264
- if let Some ( ( deleted_state_root, removed_state ) ) =
264
+ if let Some ( ( deleted_state_root, _ ) ) =
265
265
self . states . put ( state_root, ( state_root, state. clone ( ) ) )
266
266
{
267
267
deleted_states. push ( deleted_state_root) ;
268
- self . cached_bytes = self
269
- . cached_bytes
270
- . saturating_sub ( removed_state. memory_size ( ) ) ;
271
268
}
272
-
273
269
// Record the connection from block root and slot to this state.
274
270
let slot = state. slot ( ) ;
275
271
self . block_map . insert ( block_root, slot, state_root) ;
276
- self . cached_bytes += state_size;
272
+ self . put_count += 1 ;
273
+
274
+ if self . put_count >= RECOMPUTE_INTERVAL {
275
+ self . recompute_cached_bytes ( ) ;
276
+ self . put_count = 0 ;
277
+ }
277
278
278
279
Ok ( PutStateOutcome :: New ( deleted_states) )
279
280
}
@@ -340,11 +341,6 @@ impl<E: EthSpec> StateCache<E> {
340
341
}
341
342
342
343
pub fn delete_state ( & mut self , state_root : & Hash256 ) {
343
- self . cached_bytes = self . cached_bytes . saturating_sub (
344
- self . states
345
- . peek ( state_root)
346
- . map_or ( 0 , |( _, state) | state. memory_size ( ) ) ,
347
- ) ;
348
344
self . states . pop ( state_root) ;
349
345
self . block_map . delete ( state_root) ;
350
346
}
@@ -425,6 +421,43 @@ impl<E: EthSpec> StateCache<E> {
425
421
426
422
state_roots_to_delete
427
423
}
424
+
425
+ fn recompute_cached_bytes ( & mut self ) {
426
+ let mut total_bytes: usize = self
427
+ . states
428
+ . iter ( )
429
+ . map ( |( _, ( _, state) ) | state. memory_size ( ) )
430
+ . sum ( ) ;
431
+
432
+ self . cached_bytes = total_bytes;
433
+
434
+ // Update the metric
435
+ metrics:: set_gauge (
436
+ & metrics:: STORE_BEACON_STATE_CACHE_MEMORY_SIZE ,
437
+ total_bytes as i64 ,
438
+ ) ;
439
+
440
+ while total_bytes > self . max_cached_bytes && self . len ( ) > 0 {
441
+ // Prune a small number of states
442
+ let states_to_prune = std:: cmp:: min ( 5 , self . len ( ) ) ; // Prune up to 5 states
443
+ self . cull ( states_to_prune) ;
444
+
445
+ // Recompute to see actual memory reduction
446
+ total_bytes = self
447
+ . states
448
+ . iter ( )
449
+ . map ( |( _, ( _, state) ) | state. memory_size ( ) )
450
+ . sum ( ) ;
451
+
452
+ self . cached_bytes = total_bytes;
453
+
454
+ // Update metric again
455
+ metrics:: set_gauge (
456
+ & metrics:: STORE_BEACON_STATE_CACHE_MEMORY_SIZE ,
457
+ total_bytes as i64 ,
458
+ ) ;
459
+ }
460
+ }
428
461
}
429
462
430
463
impl BlockMap {
0 commit comments