use seqlock for AccountStorage count and status tracking (#34356)
use seqlock for appendvec count and status tracking Co-authored-by: HaoranYi <haoran.yi@solana.com>
This commit is contained in:
parent
cfb16ab76a
commit
c43edd2fef
|
@ -77,6 +77,7 @@ use {
|
||||||
log::*,
|
log::*,
|
||||||
rand::{thread_rng, Rng},
|
rand::{thread_rng, Rng},
|
||||||
rayon::{prelude::*, ThreadPool},
|
rayon::{prelude::*, ThreadPool},
|
||||||
|
seqlock::SeqLock,
|
||||||
serde::{Deserialize, Serialize},
|
serde::{Deserialize, Serialize},
|
||||||
smallvec::SmallVec,
|
smallvec::SmallVec,
|
||||||
solana_measure::{measure::Measure, measure_us},
|
solana_measure::{measure::Measure, measure_us},
|
||||||
|
@ -1012,7 +1013,7 @@ pub struct AccountStorageEntry {
|
||||||
/// any accounts in it
|
/// any accounts in it
|
||||||
/// status corresponding to the storage, lets us know that
|
/// status corresponding to the storage, lets us know that
|
||||||
/// the append_vec, once maxed out, then emptied, can be reclaimed
|
/// 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
|
/// 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
|
/// track of lifetime count of all store operations. And this differs from
|
||||||
|
@ -1035,7 +1036,7 @@ impl AccountStorageEntry {
|
||||||
id: AtomicAppendVecId::new(id),
|
id: AtomicAppendVecId::new(id),
|
||||||
slot: AtomicU64::new(slot),
|
slot: AtomicU64::new(slot),
|
||||||
accounts,
|
accounts,
|
||||||
count_and_status: RwLock::new((0, AccountStorageStatus::Available)),
|
count_and_status: SeqLock::new((0, AccountStorageStatus::Available)),
|
||||||
approx_store_count: AtomicUsize::new(0),
|
approx_store_count: AtomicUsize::new(0),
|
||||||
alive_bytes: AtomicUsize::new(0),
|
alive_bytes: AtomicUsize::new(0),
|
||||||
}
|
}
|
||||||
|
@ -1051,14 +1052,14 @@ impl AccountStorageEntry {
|
||||||
id: AtomicAppendVecId::new(id),
|
id: AtomicAppendVecId::new(id),
|
||||||
slot: AtomicU64::new(slot),
|
slot: AtomicU64::new(slot),
|
||||||
accounts,
|
accounts,
|
||||||
count_and_status: RwLock::new((0, AccountStorageStatus::Available)),
|
count_and_status: SeqLock::new((0, AccountStorageStatus::Available)),
|
||||||
approx_store_count: AtomicUsize::new(num_accounts),
|
approx_store_count: AtomicUsize::new(num_accounts),
|
||||||
alive_bytes: AtomicUsize::new(0),
|
alive_bytes: AtomicUsize::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_status(&self, mut status: AccountStorageStatus) {
|
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;
|
let count = count_and_status.0;
|
||||||
|
|
||||||
|
@ -1079,7 +1080,7 @@ impl AccountStorageEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recycle(&self, slot: Slot, id: AppendVecId) {
|
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();
|
self.accounts.reset();
|
||||||
*count_and_status = (0, AccountStorageStatus::Available);
|
*count_and_status = (0, AccountStorageStatus::Available);
|
||||||
self.slot.store(slot, Ordering::Release);
|
self.slot.store(slot, Ordering::Release);
|
||||||
|
@ -1089,11 +1090,11 @@ impl AccountStorageEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn status(&self) -> AccountStorageStatus {
|
pub fn status(&self) -> AccountStorageStatus {
|
||||||
self.count_and_status.read().unwrap().1
|
self.count_and_status.read().1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count(&self) -> usize {
|
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 {
|
pub fn approx_stored_count(&self) -> usize {
|
||||||
|
@ -1133,14 +1134,14 @@ impl AccountStorageEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_account(&self, num_bytes: usize) {
|
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);
|
*count_and_status = (count_and_status.0 + 1, count_and_status.1);
|
||||||
self.approx_store_count.fetch_add(1, Ordering::Relaxed);
|
self.approx_store_count.fetch_add(1, Ordering::Relaxed);
|
||||||
self.alive_bytes.fetch_add(num_bytes, Ordering::SeqCst);
|
self.alive_bytes.fetch_add(num_bytes, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_available(&self) -> bool {
|
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;
|
let (count, status) = *count_and_status;
|
||||||
|
|
||||||
if status == AccountStorageStatus::Available {
|
if status == AccountStorageStatus::Available {
|
||||||
|
@ -1156,7 +1157,7 @@ impl AccountStorageEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_account(&self, num_bytes: usize, reset_accounts: bool) -> usize {
|
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;
|
let (mut count, mut status) = *count_and_status;
|
||||||
|
|
||||||
if count == 1 && status == AccountStorageStatus::Full && reset_accounts {
|
if count == 1 && status == AccountStorageStatus::Full && reset_accounts {
|
||||||
|
@ -9423,7 +9424,7 @@ impl AccountsDb {
|
||||||
store.count(),
|
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);
|
assert_eq!(count_and_status.0, 0);
|
||||||
count_and_status.0 = entry.count;
|
count_and_status.0 = entry.count;
|
||||||
}
|
}
|
||||||
|
@ -9436,7 +9437,7 @@ impl AccountsDb {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
trace!("id: {} clearing count", id);
|
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();
|
storage_size_storages_time.stop();
|
||||||
|
@ -9453,7 +9454,7 @@ impl AccountsDb {
|
||||||
" slot: {} id: {} count_and_status: {:?} approx_store_count: {} len: {} capacity: {} (recycled: {:?})",
|
" slot: {} id: {} count_and_status: {:?} approx_store_count: {} len: {} capacity: {} (recycled: {:?})",
|
||||||
entry.slot(),
|
entry.slot(),
|
||||||
entry.append_vec_id(),
|
entry.append_vec_id(),
|
||||||
*entry.count_and_status.read().unwrap(),
|
entry.count_and_status.read(),
|
||||||
entry.approx_store_count.load(Ordering::Relaxed),
|
entry.approx_store_count.load(Ordering::Relaxed),
|
||||||
entry.accounts.len(),
|
entry.accounts.len(),
|
||||||
entry.accounts.capacity(),
|
entry.accounts.capacity(),
|
||||||
|
@ -9491,7 +9492,7 @@ impl AccountsDb {
|
||||||
" slot: {} id: {} count_and_status: {:?} approx_store_count: {} len: {} capacity: {}",
|
" slot: {} id: {} count_and_status: {:?} approx_store_count: {} len: {} capacity: {}",
|
||||||
slot,
|
slot,
|
||||||
entry.append_vec_id(),
|
entry.append_vec_id(),
|
||||||
*entry.count_and_status.read().unwrap(),
|
entry.count_and_status.read(),
|
||||||
entry.approx_store_count.load(Ordering::Relaxed),
|
entry.approx_store_count.load(Ordering::Relaxed),
|
||||||
entry.accounts.len(),
|
entry.accounts.len(),
|
||||||
entry.accounts.capacity(),
|
entry.accounts.capacity(),
|
||||||
|
@ -15796,7 +15797,7 @@ pub mod tests {
|
||||||
// fake out the store count to avoid the assert
|
// fake out the store count to avoid the assert
|
||||||
for (_, store) in accounts.storage.iter() {
|
for (_, store) in accounts.storage.iter() {
|
||||||
store.alive_bytes.store(0, Ordering::Release);
|
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;
|
count_and_status.0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15815,14 +15816,14 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (_, store) in accounts.storage.iter() {
|
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);
|
assert_eq!(store.alive_bytes.load(Ordering::Acquire), 0);
|
||||||
}
|
}
|
||||||
accounts.set_storage_count_and_alive_bytes(dashmap, &mut GenerateIndexTimings::default());
|
accounts.set_storage_count_and_alive_bytes(dashmap, &mut GenerateIndexTimings::default());
|
||||||
assert_eq!(accounts.storage.len(), 1);
|
assert_eq!(accounts.storage.len(), 1);
|
||||||
for (_, store) in accounts.storage.iter() {
|
for (_, store) in accounts.storage.iter() {
|
||||||
assert_eq!(store.append_vec_id(), 0);
|
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);
|
assert_eq!(store.alive_bytes.load(Ordering::Acquire), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue