From 5788e75188502fc6cfcc001fcf36f9e7945725e1 Mon Sep 17 00:00:00 2001 From: Ryo Onodera Date: Mon, 14 Dec 2020 02:58:38 +0900 Subject: [PATCH] Shrink slots by sparseness of written data size (#14072) --- runtime/src/accounts_background_service.rs | 13 ++++++--- runtime/src/accounts_db.rs | 33 ++++++++++++++++------ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/runtime/src/accounts_background_service.rs b/runtime/src/accounts_background_service.rs index 1b9f3ba612..e29eac6f9c 100644 --- a/runtime/src/accounts_background_service.rs +++ b/runtime/src/accounts_background_service.rs @@ -257,10 +257,15 @@ impl AccountsBackgroundService { assert!(last_cleaned_block_height <= snapshot_block_height); last_cleaned_block_height = snapshot_block_height; } else { - consumed_budget = bank.process_stale_slot_with_budget( - consumed_budget, - SHRUNKEN_ACCOUNT_PER_INTERVAL, - ); + // under sustained writes, shrink can lag behind so cap to + // SHRUNKEN_ACCOUNT_PER_INTERVAL (which is based on INTERVAL_MS, + // which in turn roughly asscociated block time) + consumed_budget = bank + .process_stale_slot_with_budget( + consumed_budget, + SHRUNKEN_ACCOUNT_PER_INTERVAL, + ) + .min(SHRUNKEN_ACCOUNT_PER_INTERVAL); if bank.block_height() - last_cleaned_block_height > (CLEAN_INTERVAL_BLOCKS + thread_rng().gen_range(0, 10)) diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 67b0e3786d..07f315b3cc 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -266,6 +266,14 @@ impl AccountStorageEntry { self.approx_store_count.load(Ordering::Relaxed) } + pub fn written_bytes(&self) -> u64 { + self.accounts.len() as u64 + } + + pub fn total_bytes(&self) -> u64 { + self.accounts.capacity() + } + pub fn has_accounts(&self) -> bool { self.count() > 0 } @@ -1019,9 +1027,13 @@ impl AccountsDB { let stores = stores_lock.read().unwrap(); let mut alive_count = 0; let mut stored_count = 0; + let mut written_bytes = 0; + let mut total_bytes = 0; for store in stores.values() { alive_count += store.count(); stored_count += store.approx_stored_count(); + written_bytes += store.written_bytes(); + total_bytes += store.total_bytes(); } if alive_count == stored_count && stores.values().len() == 1 { trace!( @@ -1032,14 +1044,17 @@ impl AccountsDB { if forced { " (forced)" } else { "" }, ); return 0; - } else if (alive_count as f32 / stored_count as f32) >= 0.80 && !forced { - trace!( - "shrink_stale_slot ({}): not enough space to shrink: {} / {}", - slot, - alive_count, - stored_count, + } else if !forced { + let sparse_by_count = (alive_count as f32 / stored_count as f32) <= 0.8; + let sparse_by_bytes = (written_bytes as f32 / total_bytes as f32) <= 0.8; + let skip_shrink = !sparse_by_count && !sparse_by_bytes; + info!( + "shrink_stale_slot ({}): skip_shrink: {} count: {}/{} byte: {}/{}", + slot, skip_shrink, alive_count, stored_count, written_bytes, total_bytes, ); - return 0; + if skip_shrink { + return 0; + } } for store in stores.values() { let mut start = 0; @@ -5293,7 +5308,7 @@ pub mod tests { let accounts = AccountsDB::new_single(); - let pubkey_count = 100; + let pubkey_count = 30000; let pubkeys: Vec<_> = (0..pubkey_count) .map(|_| solana_sdk::pubkey::new_rand()) .collect(); @@ -5314,7 +5329,7 @@ pub mod tests { accounts.add_root(current_slot); current_slot += 1; - let pubkey_count_after_shrink = 90; + let pubkey_count_after_shrink = 25000; let updated_pubkeys = &pubkeys[0..pubkey_count - pubkey_count_after_shrink]; for pubkey in updated_pubkeys {