hold items with ref count != 1 in memory (#30414)
* hold items with ref count != 1 in memory * fix tests
This commit is contained in:
parent
08d71ae8a1
commit
db8764f98d
|
@ -12,6 +12,7 @@ const STATS_INTERVAL_MS: u64 = 10_000;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct BucketMapHolderStats {
|
pub struct BucketMapHolderStats {
|
||||||
|
pub held_in_mem_ref_count: AtomicU64,
|
||||||
pub held_in_mem_slot_list_len: AtomicU64,
|
pub held_in_mem_slot_list_len: AtomicU64,
|
||||||
pub held_in_mem_slot_list_cached: AtomicU64,
|
pub held_in_mem_slot_list_cached: AtomicU64,
|
||||||
pub get_mem_us: AtomicU64,
|
pub get_mem_us: AtomicU64,
|
||||||
|
@ -252,6 +253,11 @@ impl BucketMapHolderStats {
|
||||||
self.held_in_mem_slot_list_len.swap(0, Ordering::Relaxed),
|
self.held_in_mem_slot_list_len.swap(0, Ordering::Relaxed),
|
||||||
i64
|
i64
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"held_in_mem_ref_count",
|
||||||
|
self.held_in_mem_ref_count.swap(0, Ordering::Relaxed),
|
||||||
|
i64
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"held_in_mem_slot_list_cached",
|
"held_in_mem_slot_list_cached",
|
||||||
self.held_in_mem_slot_list_cached.swap(0, Ordering::Relaxed),
|
self.held_in_mem_slot_list_cached.swap(0, Ordering::Relaxed),
|
||||||
|
|
|
@ -949,6 +949,9 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
if exceeds_budget {
|
if exceeds_budget {
|
||||||
// if we are already holding too many items in-mem, then we need to be more aggressive at kicking things out
|
// if we are already holding too many items in-mem, then we need to be more aggressive at kicking things out
|
||||||
(true, None)
|
(true, None)
|
||||||
|
} else if entry.ref_count() != 1 {
|
||||||
|
Self::update_stat(&self.stats().held_in_mem_ref_count, 1);
|
||||||
|
(false, None)
|
||||||
} else {
|
} else {
|
||||||
// only read the slot list if we are planning to throw the item out
|
// only read the slot list if we are planning to throw the item out
|
||||||
let slot_list = entry.slot_list.read().unwrap();
|
let slot_list = entry.slot_list.read().unwrap();
|
||||||
|
@ -1136,6 +1139,8 @@ impl<T: IndexValue> InMemAccountsIndex<T> {
|
||||||
// not evicting, so don't write, even if dirty
|
// not evicting, so don't write, even if dirty
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if v.ref_count() != 1 {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
// if we are evicting it, then we need to update disk if we're dirty
|
// if we are evicting it, then we need to update disk if we're dirty
|
||||||
if v.clear_dirty() {
|
if v.clear_dirty() {
|
||||||
|
@ -1452,13 +1457,42 @@ mod tests {
|
||||||
bucket
|
bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_should_evict_from_mem_ref_count() {
|
||||||
|
for ref_count in [0, 1, 2] {
|
||||||
|
let bucket = new_for_test::<u64>();
|
||||||
|
let startup = false;
|
||||||
|
let current_age = 0;
|
||||||
|
let one_element_slot_list = vec![(0, 0)];
|
||||||
|
let one_element_slot_list_entry = Arc::new(AccountMapEntryInner::new(
|
||||||
|
one_element_slot_list,
|
||||||
|
ref_count,
|
||||||
|
AccountMapEntryMeta::default(),
|
||||||
|
));
|
||||||
|
|
||||||
|
// exceeded budget
|
||||||
|
assert_eq!(
|
||||||
|
bucket
|
||||||
|
.should_evict_from_mem(
|
||||||
|
current_age,
|
||||||
|
&one_element_slot_list_entry,
|
||||||
|
startup,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.0,
|
||||||
|
ref_count == 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_should_evict_from_mem() {
|
fn test_should_evict_from_mem() {
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
let bucket = new_for_test::<u64>();
|
let bucket = new_for_test::<u64>();
|
||||||
let mut startup = false;
|
let mut startup = false;
|
||||||
let mut current_age = 0;
|
let mut current_age = 0;
|
||||||
let ref_count = 0;
|
let ref_count = 1;
|
||||||
let one_element_slot_list = vec![(0, 0)];
|
let one_element_slot_list = vec![(0, 0)];
|
||||||
let one_element_slot_list_entry = Arc::new(AccountMapEntryInner::new(
|
let one_element_slot_list_entry = Arc::new(AccountMapEntryInner::new(
|
||||||
one_element_slot_list,
|
one_element_slot_list,
|
||||||
|
|
Loading…
Reference in New Issue