From c43edd2fef4a855f11af3db00c38ad8d0208cae3 Mon Sep 17 00:00:00 2001 From: HaoranYi Date: Fri, 8 Dec 2023 08:49:54 -0600 Subject: [PATCH] use seqlock for AccountStorage count and status tracking (#34356) use seqlock for appendvec count and status tracking Co-authored-by: HaoranYi --- accounts-db/src/accounts_db.rs | 35 +++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index 59e2b8f6bec56a..60e3827e4af46a 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -77,6 +77,7 @@ use { log::*, rand::{thread_rng, Rng}, rayon::{prelude::*, ThreadPool}, + seqlock::SeqLock, serde::{Deserialize, Serialize}, smallvec::SmallVec, solana_measure::{measure::Measure, measure_us}, @@ -1012,7 +1013,7 @@ pub struct AccountStorageEntry { /// any accounts in it /// status corresponding to the storage, lets us know that /// the append_vec, once maxed out, then emptied, can be reclaimed - count_and_status: RwLock<(usize, AccountStorageStatus)>, + count_and_status: SeqLock<(usize, AccountStorageStatus)>, /// This is the total number of accounts stored ever since initialized to keep /// track of lifetime count of all store operations. And this differs from @@ -1035,7 +1036,7 @@ impl AccountStorageEntry { id: AtomicAppendVecId::new(id), slot: AtomicU64::new(slot), accounts, - count_and_status: RwLock::new((0, AccountStorageStatus::Available)), + count_and_status: SeqLock::new((0, AccountStorageStatus::Available)), approx_store_count: AtomicUsize::new(0), alive_bytes: AtomicUsize::new(0), } @@ -1051,14 +1052,14 @@ impl AccountStorageEntry { id: AtomicAppendVecId::new(id), slot: AtomicU64::new(slot), accounts, - count_and_status: RwLock::new((0, AccountStorageStatus::Available)), + count_and_status: SeqLock::new((0, AccountStorageStatus::Available)), approx_store_count: AtomicUsize::new(num_accounts), alive_bytes: AtomicUsize::new(0), } } pub fn set_status(&self, mut status: AccountStorageStatus) { - let mut count_and_status = self.count_and_status.write().unwrap(); + let mut count_and_status = self.count_and_status.lock_write(); let count = count_and_status.0; @@ -1079,7 +1080,7 @@ impl AccountStorageEntry { } pub fn recycle(&self, slot: Slot, id: AppendVecId) { - let mut count_and_status = self.count_and_status.write().unwrap(); + let mut count_and_status = self.count_and_status.lock_write(); self.accounts.reset(); *count_and_status = (0, AccountStorageStatus::Available); self.slot.store(slot, Ordering::Release); @@ -1089,11 +1090,11 @@ impl AccountStorageEntry { } pub fn status(&self) -> AccountStorageStatus { - self.count_and_status.read().unwrap().1 + self.count_and_status.read().1 } pub fn count(&self) -> usize { - self.count_and_status.read().unwrap().0 + self.count_and_status.read().0 } pub fn approx_stored_count(&self) -> usize { @@ -1133,14 +1134,14 @@ impl AccountStorageEntry { } fn add_account(&self, num_bytes: usize) { - let mut count_and_status = self.count_and_status.write().unwrap(); + let mut count_and_status = self.count_and_status.lock_write(); *count_and_status = (count_and_status.0 + 1, count_and_status.1); self.approx_store_count.fetch_add(1, Ordering::Relaxed); self.alive_bytes.fetch_add(num_bytes, Ordering::SeqCst); } fn try_available(&self) -> bool { - let mut count_and_status = self.count_and_status.write().unwrap(); + let mut count_and_status = self.count_and_status.lock_write(); let (count, status) = *count_and_status; if status == AccountStorageStatus::Available { @@ -1156,7 +1157,7 @@ impl AccountStorageEntry { } fn remove_account(&self, num_bytes: usize, reset_accounts: bool) -> usize { - let mut count_and_status = self.count_and_status.write().unwrap(); + let mut count_and_status = self.count_and_status.lock_write(); let (mut count, mut status) = *count_and_status; if count == 1 && status == AccountStorageStatus::Full && reset_accounts { @@ -9423,7 +9424,7 @@ impl AccountsDb { store.count(), ); { - let mut count_and_status = store.count_and_status.write().unwrap(); + let mut count_and_status = store.count_and_status.lock_write(); assert_eq!(count_and_status.0, 0); count_and_status.0 = entry.count; } @@ -9436,7 +9437,7 @@ impl AccountsDb { ); } else { trace!("id: {} clearing count", id); - store.count_and_status.write().unwrap().0 = 0; + store.count_and_status.lock_write().0 = 0; } } storage_size_storages_time.stop(); @@ -9453,7 +9454,7 @@ impl AccountsDb { " slot: {} id: {} count_and_status: {:?} approx_store_count: {} len: {} capacity: {} (recycled: {:?})", entry.slot(), entry.append_vec_id(), - *entry.count_and_status.read().unwrap(), + entry.count_and_status.read(), entry.approx_store_count.load(Ordering::Relaxed), entry.accounts.len(), entry.accounts.capacity(), @@ -9491,7 +9492,7 @@ impl AccountsDb { " slot: {} id: {} count_and_status: {:?} approx_store_count: {} len: {} capacity: {}", slot, entry.append_vec_id(), - *entry.count_and_status.read().unwrap(), + entry.count_and_status.read(), entry.approx_store_count.load(Ordering::Relaxed), entry.accounts.len(), entry.accounts.capacity(), @@ -15796,7 +15797,7 @@ pub mod tests { // fake out the store count to avoid the assert for (_, store) in accounts.storage.iter() { store.alive_bytes.store(0, Ordering::Release); - let mut count_and_status = store.count_and_status.write().unwrap(); + let mut count_and_status = store.count_and_status.lock_write(); count_and_status.0 = 0; } @@ -15815,14 +15816,14 @@ pub mod tests { ); for (_, store) in accounts.storage.iter() { - assert_eq!(store.count_and_status.read().unwrap().0, 0); + assert_eq!(store.count_and_status.read().0, 0); assert_eq!(store.alive_bytes.load(Ordering::Acquire), 0); } accounts.set_storage_count_and_alive_bytes(dashmap, &mut GenerateIndexTimings::default()); assert_eq!(accounts.storage.len(), 1); for (_, store) in accounts.storage.iter() { assert_eq!(store.append_vec_id(), 0); - assert_eq!(store.count_and_status.read().unwrap().0, count); + assert_eq!(store.count_and_status.read().0, count); assert_eq!(store.alive_bytes.load(Ordering::Acquire), 2); } }