From a458839ff1114c614ca416f17c4bf2c2da9c9af6 Mon Sep 17 00:00:00 2001 From: dmakarov Date: Tue, 15 Oct 2024 19:33:54 -0400 Subject: [PATCH] Use VecDeque for best_ancient_slots_to_shrink to avoid vec reversing (#3187) --- accounts-db/src/accounts_db.rs | 14 ++++++-------- accounts-db/src/ancient_append_vecs.rs | 13 +++++-------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/accounts-db/src/accounts_db.rs b/accounts-db/src/accounts_db.rs index e2353b99fce81d..b16d5700157609 100644 --- a/accounts-db/src/accounts_db.rs +++ b/accounts-db/src/accounts_db.rs @@ -97,7 +97,7 @@ use { std::{ borrow::Cow, boxed::Box, - collections::{BTreeSet, HashMap, HashSet}, + collections::{BTreeSet, HashMap, HashSet, VecDeque}, fs, hash::{Hash as StdHash, Hasher as StdHasher}, io::Result as IoResult, @@ -1508,12 +1508,11 @@ pub struct AccountsDb { pub is_experimental_accumulator_hash_enabled: AtomicBool, /// These are the ancient storages that could be valuable to - /// shrink, sorted by amount of dead bytes. The elements - /// are popped from the end of the vector, hence the sorting is - /// expected to be from the smallest dead bytes to the largest. + /// shrink, sorted by amount of dead bytes. The elements + /// are sorted from the largest dead bytes to the smallest. /// Members are Slot and capacity. If capacity is smaller, then /// that means the storage was already shrunk. - pub(crate) best_ancient_slots_to_shrink: RwLock>, + pub(crate) best_ancient_slots_to_shrink: RwLock>, } /// results from 'split_storages_ancient' @@ -4442,11 +4441,10 @@ impl AccountsDb { }); // If there are too few slots to shrink, add an ancient slot - // for shrinking. The best ancient slots to shrink are - // assumed to be in reverse order. + // for shrinking. if shrink_slots.len() < SHRINK_INSERT_ANCIENT_THRESHOLD { let mut ancients = self.best_ancient_slots_to_shrink.write().unwrap(); - while let Some((slot, capacity)) = ancients.pop() { + while let Some((slot, capacity)) = ancients.pop_front() { if let Some(store) = self.storage.get_slot_storage_entry(slot) { if !shrink_slots.contains(&slot) && capacity == store.capacity() diff --git a/accounts-db/src/ancient_append_vecs.rs b/accounts-db/src/ancient_append_vecs.rs index 5d645c9560cc39..148c543b4c6302 100644 --- a/accounts-db/src/ancient_append_vecs.rs +++ b/accounts-db/src/ancient_append_vecs.rs @@ -21,7 +21,7 @@ use { solana_measure::measure_us, solana_sdk::clock::Slot, std::{ - collections::HashMap, + collections::{HashMap, VecDeque}, num::{NonZeroU64, Saturating}, sync::{atomic::Ordering, Arc, Mutex}, }, @@ -81,7 +81,7 @@ struct AncientSlotInfos { total_alive_bytes: Saturating, /// slots that have dead accounts and thus the corresponding slot /// storages can be shrunk - best_slots_to_shrink: Vec<(Slot, u64)>, + best_slots_to_shrink: VecDeque<(Slot, u64)>, } impl AncientSlotInfos { @@ -183,10 +183,11 @@ impl AncientSlotInfos { // At this point self.shrink_indexes have been sorted by the // largest amount of dead bytes first in the corresponding // storages. - self.best_slots_to_shrink = Vec::with_capacity(self.shrink_indexes.len()); + self.best_slots_to_shrink = VecDeque::with_capacity(self.shrink_indexes.len()); for info_index in &self.shrink_indexes { let info = &mut self.all_infos[*info_index]; - self.best_slots_to_shrink.push((info.slot, info.capacity)); + self.best_slots_to_shrink + .push_back((info.slot, info.capacity)); if bytes_to_shrink_due_to_ratio.0 >= threshold_bytes { // we exceeded the amount to shrink due to alive ratio, so don't shrink this one just due to 'should_shrink' // It MAY be shrunk based on total capacity still. @@ -196,10 +197,6 @@ impl AncientSlotInfos { bytes_to_shrink_due_to_ratio += info.alive_bytes; } } - // Reverse the vector so that the elements with the largest - // dead bytes are popped first when used to extend the - // shrinking candidates. - self.best_slots_to_shrink.reverse(); } /// after this function, only slots that were chosen to shrink are marked with