Do not evict tombstones (#31311)

This commit is contained in:
Pankaj Garg 2023-04-21 16:36:22 -07:00 committed by GitHub
parent d7ad0ce093
commit a35e31f269
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 36 additions and 26 deletions

View File

@ -27,7 +27,6 @@ use {
const MAX_LOADED_ENTRY_COUNT: usize = 256;
const MAX_UNLOADED_ENTRY_COUNT: usize = 1024;
const MAX_TOMBSTONE_COUNT: usize = 1024;
/// Relationship between two fork IDs
#[derive(Copy, Clone, PartialEq)]
@ -395,12 +394,10 @@ impl LoadedPrograms {
pub fn sort_and_evict(&mut self, shrink_to: PercentageInteger) {
let mut num_loaded: usize = 0;
let mut num_unloaded: usize = 0;
let mut num_tombstones: usize = 0;
// Find eviction candidates and sort by their type and usage counters.
// Sorted result will have the following order:
// Loaded entries with ascending order of their usage count
// Unloaded entries with ascending order of their usage count
// Tombstones with ascending order of their usage count
let (ordering, sorted_candidates): (Vec<u32>, Vec<(Pubkey, Arc<LoadedProgram>)>) = self
.entries
.iter()
@ -415,8 +412,8 @@ impl LoadedPrograms {
LoadedProgramType::Unloaded => Some((1, (*id, program.clone()))),
LoadedProgramType::FailedVerification
| LoadedProgramType::Closed
| LoadedProgramType::DelayVisibility => Some((2, (*id, program.clone()))),
LoadedProgramType::BuiltIn(_) => None,
| LoadedProgramType::DelayVisibility
| LoadedProgramType::BuiltIn(_) => None,
})
})
.sorted_by_cached_key(|(order, (_id, program))| {
@ -428,7 +425,6 @@ impl LoadedPrograms {
match order {
0 => num_loaded = num_loaded.saturating_add(1),
1 => num_unloaded = num_unloaded.saturating_add(1),
2 => num_tombstones = num_tombstones.saturating_add(1),
_ => unreachable!(),
}
}
@ -451,11 +447,6 @@ impl LoadedPrograms {
.take(num_newly_unloaded_to_evict),
);
let num_tombstones_to_evict =
num_tombstones.saturating_sub(shrink_to.apply_to(MAX_TOMBSTONE_COUNT));
let (_, sorted_candidates) = sorted_candidates.split_at(num_unloaded);
self.remove_program_entries(sorted_candidates.iter().take(num_tombstones_to_evict));
self.remove_programs_with_no_entries();
}
@ -539,14 +530,13 @@ mod tests {
})
}
fn set_tombstone(cache: &mut LoadedPrograms, key: Pubkey, slot: Slot) -> Arc<LoadedProgram> {
cache.assign_program(
key,
Arc::new(LoadedProgram::new_tombstone(
slot,
LoadedProgramType::FailedVerification,
)),
)
fn set_tombstone(
cache: &mut LoadedPrograms,
key: Pubkey,
slot: Slot,
reason: LoadedProgramType,
) -> Arc<LoadedProgram> {
cache.assign_program(key, Arc::new(LoadedProgram::new_tombstone(slot, reason)))
}
fn insert_unloaded_program(
@ -603,7 +593,12 @@ mod tests {
});
for slot in 21..31 {
set_tombstone(&mut cache, program1, slot);
set_tombstone(
&mut cache,
program1,
slot,
LoadedProgramType::FailedVerification,
);
}
for slot in 31..41 {
@ -631,7 +626,12 @@ mod tests {
});
for slot in 21..31 {
set_tombstone(&mut cache, program2, slot);
set_tombstone(
&mut cache,
program2,
slot,
LoadedProgramType::DelayVisibility,
);
}
for slot in 31..41 {
@ -659,7 +659,7 @@ mod tests {
});
for slot in 21..31 {
set_tombstone(&mut cache, program3, slot);
set_tombstone(&mut cache, program3, slot, LoadedProgramType::Closed);
}
for slot in 31..41 {
@ -690,7 +690,7 @@ mod tests {
// Evicting to 2% should update cache with
// * 5 active entries
// * 20 unloaded entries
// * 20 tombstones
// * 30 tombstones (tombstones are not evicted)
cache.sort_and_evict(Percentage::from(2));
// Check that every program is still in the cache.
programs.iter().for_each(|entry| {
@ -730,7 +730,7 @@ mod tests {
assert_eq!(num_loaded, 5);
assert_eq!(num_unloaded, 20);
assert_eq!(num_tombstones, 20);
assert_eq!(num_tombstones, 30);
}
#[test]
@ -877,7 +877,12 @@ mod tests {
let mut cache = LoadedPrograms::default();
let program1 = Pubkey::new_unique();
let tombstone = set_tombstone(&mut cache, program1, 10);
let tombstone = set_tombstone(
&mut cache,
program1,
10,
LoadedProgramType::FailedVerification,
);
let second_level = &cache
.entries
.get(&program1)
@ -901,7 +906,12 @@ mod tests {
assert_eq!(second_level.len(), 1);
assert!(!second_level.get(0).unwrap().is_tombstone());
let tombstone = set_tombstone(&mut cache, program2, 60);
let tombstone = set_tombstone(
&mut cache,
program2,
60,
LoadedProgramType::FailedVerification,
);
let second_level = &cache
.entries
.get(&program2)