diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 693cd83473..d1693abd69 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -6921,10 +6921,10 @@ impl AccountsDb { .account_maps .iter() .map(|map_bin| { - let len = map_bin.read().unwrap().len(); + let len = map_bin.read().unwrap().len_for_stats(); min_bin_size = std::cmp::min(min_bin_size, len); max_bin_size = std::cmp::max(max_bin_size, len); - len + len as usize }) .sum(); diff --git a/runtime/src/accounts_index.rs b/runtime/src/accounts_index.rs index b85d0c816d..71aaa84e79 100644 --- a/runtime/src/accounts_index.rs +++ b/runtime/src/accounts_index.rs @@ -3052,10 +3052,10 @@ pub mod tests { let new_entry = PreAllocatedAccountMapEntry::new(slot, account_info, &index.storage.storage, false); - assert_eq!(0, account_maps_len_expensive(&index)); + assert_eq!(0, account_maps_stats_len(&index)); assert_eq!((slot, account_info), new_entry.clone().into()); - assert_eq!(0, account_maps_len_expensive(&index)); + assert_eq!(0, account_maps_stats_len(&index)); let w_account_maps = index.get_account_maps_write_lock(&key.pubkey()); w_account_maps.upsert( &key.pubkey(), @@ -3064,7 +3064,7 @@ pub mod tests { UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE, ); drop(w_account_maps); - assert_eq!(1, account_maps_len_expensive(&index)); + assert_eq!(1, account_maps_stats_len(&index)); let mut ancestors = Ancestors::default(); assert!(index.get(&key.pubkey(), Some(&ancestors), None).is_none()); @@ -3615,12 +3615,8 @@ pub mod tests { assert!(found_key); } - fn account_maps_len_expensive(index: &AccountsIndex) -> usize { - index - .account_maps - .iter() - .map(|bin_map| bin_map.read().unwrap().len()) - .sum() + fn account_maps_stats_len(index: &AccountsIndex) -> usize { + index.storage.storage.stats.total_count() } #[test] @@ -3628,7 +3624,7 @@ pub mod tests { let key = Keypair::new(); let index = AccountsIndex::::default_for_tests(); let mut gc = Vec::new(); - assert_eq!(0, account_maps_len_expensive(&index)); + assert_eq!(0, account_maps_stats_len(&index)); index.upsert( 1, &key.pubkey(), @@ -3639,7 +3635,7 @@ pub mod tests { &mut gc, UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE, ); - assert_eq!(1, account_maps_len_expensive(&index)); + assert_eq!(1, account_maps_stats_len(&index)); index.upsert( 1, @@ -3651,7 +3647,7 @@ pub mod tests { &mut gc, UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE, ); - assert_eq!(1, account_maps_len_expensive(&index)); + assert_eq!(1, account_maps_stats_len(&index)); let purges = index.purge_roots(&key.pubkey()); assert_eq!(purges, (vec![], false)); @@ -3660,7 +3656,7 @@ pub mod tests { let purges = index.purge_roots(&key.pubkey()); assert_eq!(purges, (vec![(1, 10)], true)); - assert_eq!(1, account_maps_len_expensive(&index)); + assert_eq!(1, account_maps_stats_len(&index)); index.upsert( 1, &key.pubkey(), @@ -3671,7 +3667,7 @@ pub mod tests { &mut gc, UPSERT_PREVIOUS_SLOT_ENTRY_WAS_CACHED_FALSE, ); - assert_eq!(1, account_maps_len_expensive(&index)); + assert_eq!(1, account_maps_stats_len(&index)); } #[test] diff --git a/runtime/src/bucket_map_holder_stats.rs b/runtime/src/bucket_map_holder_stats.rs index 4745fd0691..77d4760fb3 100644 --- a/runtime/src/bucket_map_holder_stats.rs +++ b/runtime/src/bucket_map_holder_stats.rs @@ -2,7 +2,7 @@ use crate::accounts_index::IndexValue; use crate::bucket_map_holder::BucketMapHolder; use solana_sdk::timing::AtomicInterval; use std::fmt::Debug; -use std::sync::atomic::{AtomicBool, AtomicU64, AtomicU8, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU64, AtomicU8, AtomicUsize, Ordering}; // stats logged every 10 s const STATS_INTERVAL_MS: u64 = 10_000; @@ -28,11 +28,11 @@ pub struct BucketMapHolderStats { pub keys: AtomicU64, pub deletes: AtomicU64, pub inserts: AtomicU64, - count: AtomicU64, + count: AtomicUsize, pub bg_waiting_us: AtomicU64, pub bg_throttling_wait_us: AtomicU64, - pub count_in_mem: AtomicU64, - pub per_bucket_count: Vec, + pub count_in_mem: AtomicUsize, + pub per_bucket_count: Vec, pub flush_entries_updated_on_disk: AtomicU64, pub flush_entries_removed_from_mem: AtomicU64, pub active_threads: AtomicU64, @@ -53,7 +53,7 @@ impl BucketMapHolderStats { bins: bins as u64, per_bucket_count: (0..bins) .into_iter() - .map(|_| AtomicU64::default()) + .map(|_| AtomicUsize::default()) .collect(), ..BucketMapHolderStats::default() } @@ -73,7 +73,7 @@ impl BucketMapHolderStats { self.insert_or_delete_mem_count(insert, bin, 1) } - pub fn insert_or_delete_mem_count(&self, insert: bool, bin: usize, count: u64) { + pub fn insert_or_delete_mem_count(&self, insert: bool, bin: usize, count: usize) { let per_bucket = self.per_bucket_count.get(bin); if insert { self.count_in_mem.fetch_add(count, Ordering::Relaxed); @@ -113,7 +113,7 @@ impl BucketMapHolderStats { } /// return min, max, sum, median of data - fn get_stats(mut data: Vec) -> (u64, u64, u64, u64) { + fn get_stats(mut data: Vec) -> (usize, usize, usize, usize) { if data.is_empty() { (0, 0, 0, 0) } else { @@ -135,6 +135,18 @@ impl BucketMapHolderStats { } } + pub fn total_count(&self) -> usize { + self.count.load(Ordering::Relaxed) + } + + pub fn count_in_bucket(&self, bucket: usize) -> usize { + if bucket < self.per_bucket_count.len() { + self.per_bucket_count[bucket].load(Ordering::Relaxed) + } else { + 0 + } + } + pub fn report_stats(&self, storage: &BucketMapHolder) { let elapsed_ms = self.last_time.elapsed_ms(); if elapsed_ms < STATS_INTERVAL_MS { @@ -158,7 +170,7 @@ impl BucketMapHolderStats { disk.stats .per_bucket_count .iter() - .map(|count| count.load(Ordering::Relaxed)) + .map(|count| count.load(Ordering::Relaxed) as usize) .collect::>() }) .unwrap_or_default(); @@ -186,7 +198,7 @@ impl BucketMapHolderStats { self.count_in_mem.load(Ordering::Relaxed), i64 ), - ("count", self.count.load(Ordering::Relaxed), i64), + ("count", self.total_count(), i64), ( "bg_waiting_percent", Self::calc_percent( @@ -424,7 +436,7 @@ impl BucketMapHolderStats { self.count_in_mem.load(Ordering::Relaxed), i64 ), - ("count", self.count.load(Ordering::Relaxed), i64), + ("count", self.total_count(), i64), ( "bg_waiting_percent", Self::calc_percent( diff --git a/runtime/src/in_mem_accounts_index.rs b/runtime/src/in_mem_accounts_index.rs index f7a4c37564..0d7f106a46 100644 --- a/runtime/src/in_mem_accounts_index.rs +++ b/runtime/src/in_mem_accounts_index.rs @@ -463,12 +463,8 @@ impl InMemAccountsIndex { )) } - pub fn len(&self) -> usize { - self.map().read().unwrap().len() - } - - pub fn is_empty(&self) -> bool { - self.len() == 0 + pub fn len_for_stats(&self) -> usize { + self.stats().count_in_bucket(self.bin) } fn insert_returner( @@ -880,12 +876,12 @@ impl InMemAccountsIndex { } self.stats() .insert_or_delete_mem_count(false, self.bin, removed); - Self::update_stat(&self.stats().flush_entries_removed_from_mem, removed); + Self::update_stat(&self.stats().flush_entries_removed_from_mem, removed as u64); completed_scan } - fn stats(&self) -> &BucketMapHolderStats { + pub fn stats(&self) -> &BucketMapHolderStats { &self.storage.stats }