|
1 | 1 | use crate::hdiff::HDiffBuffer;
|
2 | 2 | use crate::{
|
3 |
| - memsize::BeaconStateMemorySize, |
| 3 | + memsize::{BeaconStateWrapper, BeaconStateMemorySize}, |
4 | 4 | Error,
|
5 | 5 | metrics::{self, HOT_METRIC},
|
6 | 6 | };
|
7 | 7 | use lru::LruCache;
|
| 8 | +use milhouse::mem::MemoryTracker; |
8 | 9 | use std::collections::{BTreeMap, HashMap, HashSet};
|
9 | 10 | use std::num::NonZeroUsize;
|
| 11 | +use std::time::{Duration, Instant}; |
10 | 12 | use tracing::instrument;
|
11 | 13 | use types::{BeaconState, ChainSpec, Epoch, EthSpec, Hash256, Slot};
|
12 | 14 | /// Fraction of the LRU cache to leave intact during culling.
|
@@ -204,10 +206,10 @@ impl<E: EthSpec> StateCache<E> {
|
204 | 206 | // Do not attempt to rebase states prior to the finalized state. This method might be called
|
205 | 207 | // with states on the hdiff grid prior to finalization, as part of the reconstruction of
|
206 | 208 | // some later unfinalized state.
|
207 |
| - if let Some(finalized_state) = &self.finalized_state |
208 |
| - && state.slot() >= finalized_state.state.slot() |
209 |
| - { |
210 |
| - state.rebase_on(&finalized_state.state, spec)?; |
| 209 | + if let Some(finalized_state) = &self.finalized_state { |
| 210 | + if state.slot() >= finalized_state.state.slot() { |
| 211 | + state.rebase_on(&finalized_state.state, spec)?; |
| 212 | + } |
211 | 213 | }
|
212 | 214 |
|
213 | 215 | Ok(())
|
@@ -422,40 +424,62 @@ impl<E: EthSpec> StateCache<E> {
|
422 | 424 | state_roots_to_delete
|
423 | 425 | }
|
424 | 426 |
|
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(); |
| 427 | + fn measure_cached_memory_size(&self) -> (usize, Duration) { |
| 428 | + let mut tracker = MemoryTracker::default(); |
| 429 | + let mut total_bytes: usize = 0; |
| 430 | + let timer = Instant::now(); |
| 431 | + // Use MemoryTracker on the states |
| 432 | + // if let Some(finalized_state) = &self.finalized_state { |
| 433 | + // total_bytes += tracker |
| 434 | + // .track_item(&BeaconStateWrapper(&finalized_state.state)) |
| 435 | + // .differential_size; |
| 436 | + // } |
| 437 | + for (_, (_, state)) in &self.states { |
| 438 | + total_bytes += tracker |
| 439 | + .track_item(&BeaconStateWrapper(&state)) |
| 440 | + .differential_size; |
| 441 | + } |
431 | 442 |
|
| 443 | + let elapsed_time = timer.elapsed(); |
| 444 | + (total_bytes, elapsed_time) |
| 445 | + } |
| 446 | + |
| 447 | + fn recompute_cached_bytes(&mut self) { |
| 448 | + let (mut total_bytes, _) = self.measure_cached_memory_size(); |
432 | 449 | self.cached_bytes = total_bytes;
|
433 | 450 |
|
434 |
| - // Update the metric |
| 451 | + // Update metric again |
435 | 452 | metrics::set_gauge(
|
436 | 453 | &metrics::STORE_BEACON_STATE_CACHE_MEMORY_SIZE,
|
437 | 454 | total_bytes as i64,
|
438 | 455 | );
|
439 | 456 |
|
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); |
| 457 | + let batch = self.headroom.get().max(5).min(64); // tune batch size |
444 | 458 |
|
445 |
| - // Recompute to see actual memory reduction |
446 |
| - total_bytes = self |
447 |
| - .states |
448 |
| - .iter() |
449 |
| - .map(|(_, (_, state))| state.memory_size()) |
450 |
| - .sum(); |
| 459 | + while total_bytes > self.max_cached_bytes { |
| 460 | + // Cull the cache until we are under the max_cached_bytes limit. |
| 461 | + let deleted_states = self.cull(batch); |
| 462 | + if deleted_states.is_empty() { |
| 463 | + // No more states to delete, break out of the loop. |
| 464 | + break; |
| 465 | + } |
451 | 466 |
|
| 467 | + // Recalculate the memory size after culling. |
| 468 | + let (new_total_bytes, elapsed_time) = self.measure_cached_memory_size(); |
| 469 | + total_bytes = new_total_bytes; |
452 | 470 | self.cached_bytes = total_bytes;
|
453 | 471 |
|
454 |
| - // Update metric again |
| 472 | + // Update metric with the new size |
455 | 473 | metrics::set_gauge(
|
456 | 474 | &metrics::STORE_BEACON_STATE_CACHE_MEMORY_SIZE,
|
457 | 475 | total_bytes as i64,
|
458 | 476 | );
|
| 477 | + |
| 478 | + // Log the time taken for recalculation |
| 479 | + metrics::observe( |
| 480 | + &metrics::BEACON_STATE_MEMORY_SIZE_CALCULATION_TIME, |
| 481 | + elapsed_time.as_secs_f64(), |
| 482 | + ); |
459 | 483 | }
|
460 | 484 | }
|
461 | 485 | }
|
|
0 commit comments