Skip to content

Commit fee8672

Browse files
improve multi executor cache addition (solana-labs#22381)
(cherry picked from commit 4a9f4e2) Co-authored-by: Jack May <[email protected]>
1 parent 8a470d3 commit fee8672

File tree

1 file changed

+54
-36
lines changed

1 file changed

+54
-36
lines changed

runtime/src/bank.rs

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,23 @@ impl CachedExecutors {
443443
})
444444
}
445445

446-
fn put(&mut self, pubkey: &Pubkey, executor: Arc<dyn Executor>) {
447-
let entry = if let Some(mut entry) = self.executors.remove(pubkey) {
448-
saturating_add_assign!(self.stats.hits, 1);
449-
entry.executor = executor;
450-
entry
451-
} else {
452-
saturating_add_assign!(self.stats.misses, 1);
446+
fn put(&mut self, executors: &[(&Pubkey, Arc<dyn Executor>)]) {
447+
let mut new_executors: Vec<_> = executors
448+
.iter()
449+
.filter_map(|(key, executor)| {
450+
if let Some(mut entry) = self.executors.remove(key) {
451+
saturating_add_assign!(self.stats.hits, 1);
452+
entry.executor = executor.clone();
453+
let _ = self.executors.insert(**key, entry);
454+
None
455+
} else {
456+
saturating_add_assign!(self.stats.misses, 1);
457+
Some((*key, executor))
458+
}
459+
})
460+
.collect();
461+
462+
if !new_executors.is_empty() {
453463
let mut counts = self
454464
.executors
455465
.iter()
@@ -460,10 +470,15 @@ impl CachedExecutors {
460470
.collect::<Vec<_>>();
461471
counts.sort_unstable_by_key(|(_, count)| *count);
462472

463-
let primer_count = Self::get_primer_count(counts.as_slice());
473+
let primer_counts = Self::get_primer_counts(counts.as_slice(), new_executors.len());
464474

465475
if self.executors.len() >= self.max {
466-
if let Some(least_key) = counts.first().map(|least| *least.0) {
476+
let mut least_keys = counts
477+
.iter()
478+
.take(new_executors.len())
479+
.map(|least| *least.0)
480+
.collect::<Vec<_>>();
481+
for least_key in least_keys.drain(..) {
467482
let _ = self.executors.remove(&least_key);
468483
self.stats
469484
.evictions
@@ -473,13 +488,15 @@ impl CachedExecutors {
473488
}
474489
}
475490

476-
CachedExecutorsEntry {
477-
prev_epoch_count: 0,
478-
epoch_count: AtomicU64::new(primer_count),
479-
executor,
491+
for ((key, executor), primer_count) in new_executors.drain(..).zip(primer_counts) {
492+
let entry = CachedExecutorsEntry {
493+
prev_epoch_count: 0,
494+
epoch_count: AtomicU64::new(primer_count),
495+
executor: executor.clone(),
496+
};
497+
let _ = self.executors.insert(*key, entry);
480498
}
481-
};
482-
let _ = self.executors.insert(*pubkey, entry);
499+
}
483500
}
484501

485502
fn remove(&mut self, pubkey: &Pubkey) {
@@ -512,10 +529,13 @@ impl CachedExecutors {
512529
.unwrap_or(0)
513530
}
514531

515-
fn get_primer_count(counts: &[(&Pubkey, u64)]) -> u64 {
532+
fn get_primer_counts(counts: &[(&Pubkey, u64)], num_counts: usize) -> Vec<u64> {
516533
let max_primer_count = Self::get_primer_count_upper_bound_inclusive(counts);
517534
let mut rng = rand::thread_rng();
518-
rng.gen_range(0, max_primer_count.saturating_add(1))
535+
536+
(0..num_counts)
537+
.map(|_| rng.gen_range(0, max_primer_count.saturating_add(1)))
538+
.collect::<Vec<_>>()
519539
}
520540
}
521541

@@ -3425,9 +3445,7 @@ impl Bank {
34253445
if !dirty_executors.is_empty() {
34263446
let mut cache = self.cached_executors.write().unwrap();
34273447
let cache = Arc::make_mut(&mut cache);
3428-
for (key, executor) in dirty_executors.into_iter() {
3429-
cache.put(key, executor);
3430-
}
3448+
cache.put(&dirty_executors);
34313449
}
34323450
}
34333451

@@ -11924,17 +11942,17 @@ pub(crate) mod tests {
1192411942
let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
1192511943
let mut cache = CachedExecutors::new(3, 0);
1192611944

11927-
cache.put(&key1, executor.clone());
11928-
cache.put(&key2, executor.clone());
11929-
cache.put(&key3, executor.clone());
11945+
cache.put(&[(&key1, executor.clone())]);
11946+
cache.put(&[(&key2, executor.clone())]);
11947+
cache.put(&[(&key3, executor.clone())]);
1193011948
assert!(cache.get(&key1).is_some());
1193111949
assert!(cache.get(&key2).is_some());
1193211950
assert!(cache.get(&key3).is_some());
1193311951

1193411952
assert!(cache.get(&key1).is_some());
1193511953
assert!(cache.get(&key1).is_some());
1193611954
assert!(cache.get(&key2).is_some());
11937-
cache.put(&key4, executor.clone());
11955+
cache.put(&[(&key4, executor.clone())]);
1193811956
assert!(cache.get(&key4).is_some());
1193911957
let num_retained = [&key1, &key2, &key3]
1194011958
.iter()
@@ -11946,7 +11964,7 @@ pub(crate) mod tests {
1194611964
assert!(cache.get(&key4).is_some());
1194711965
assert!(cache.get(&key4).is_some());
1194811966
assert!(cache.get(&key4).is_some());
11949-
cache.put(&key3, executor.clone());
11967+
cache.put(&[(&key3, executor.clone())]);
1195011968
assert!(cache.get(&key3).is_some());
1195111969
let num_retained = [&key1, &key2, &key4]
1195211970
.iter()
@@ -11957,7 +11975,7 @@ pub(crate) mod tests {
1195711975
}
1195811976

1195911977
#[test]
11960-
fn test_cached_executors_eviction() {
11978+
fn test_cached_executor_eviction() {
1196111979
let key1 = solana_sdk::pubkey::new_rand();
1196211980
let key2 = solana_sdk::pubkey::new_rand();
1196311981
let key3 = solana_sdk::pubkey::new_rand();
@@ -11966,9 +11984,9 @@ pub(crate) mod tests {
1196611984
let mut cache = CachedExecutors::new(3, 0);
1196711985
assert!(cache.current_epoch == 0);
1196811986

11969-
cache.put(&key1, executor.clone());
11970-
cache.put(&key2, executor.clone());
11971-
cache.put(&key3, executor.clone());
11987+
cache.put(&[(&key1, executor.clone())]);
11988+
cache.put(&[(&key2, executor.clone())]);
11989+
cache.put(&[(&key3, executor.clone())]);
1197211990
assert!(cache.get(&key1).is_some());
1197311991
assert!(cache.get(&key1).is_some());
1197411992
assert!(cache.get(&key1).is_some());
@@ -11979,7 +11997,7 @@ pub(crate) mod tests {
1197911997
assert!(cache.get(&key2).is_some());
1198011998
assert!(cache.get(&key2).is_some());
1198111999
assert!(cache.get(&key3).is_some());
11982-
Arc::make_mut(&mut cache).put(&key4, executor.clone());
12000+
Arc::make_mut(&mut cache).put(&[(&key4, executor.clone())]);
1198312001

1198412002
assert!(cache.get(&key4).is_some());
1198512003
let num_retained = [&key1, &key2, &key3]
@@ -11989,8 +12007,8 @@ pub(crate) mod tests {
1198912007
.count();
1199012008
assert_eq!(num_retained, 2);
1199112009

11992-
Arc::make_mut(&mut cache).put(&key1, executor.clone());
11993-
Arc::make_mut(&mut cache).put(&key3, executor.clone());
12010+
Arc::make_mut(&mut cache).put(&[(&key1, executor.clone())]);
12011+
Arc::make_mut(&mut cache).put(&[(&key3, executor.clone())]);
1199412012
assert!(cache.get(&key1).is_some());
1199512013
assert!(cache.get(&key3).is_some());
1199612014
let num_retained = [&key2, &key4]
@@ -12003,7 +12021,7 @@ pub(crate) mod tests {
1200312021
cache = cache.clone_with_epoch(2);
1200412022
assert!(cache.current_epoch == 2);
1200512023

12006-
Arc::make_mut(&mut cache).put(&key3, executor.clone());
12024+
Arc::make_mut(&mut cache).put(&[(&key3, executor.clone())]);
1200712025
assert!(cache.get(&key3).is_some());
1200812026
}
1200912027

@@ -12015,11 +12033,11 @@ pub(crate) mod tests {
1201512033
let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
1201612034
let mut cache = CachedExecutors::new(2, 0);
1201712035

12018-
cache.put(&key1, executor.clone());
12036+
cache.put(&[(&key1, executor.clone())]);
1201912037
for _ in 0..5 {
1202012038
let _ = cache.get(&key1);
1202112039
}
12022-
cache.put(&key2, executor.clone());
12040+
cache.put(&[(&key2, executor.clone())]);
1202312041
// make key1's use-count for sure greater than key2's
1202412042
let _ = cache.get(&key1);
1202512043

@@ -12031,7 +12049,7 @@ pub(crate) mod tests {
1203112049
entries.sort_by_key(|(_, v)| *v);
1203212050
assert!(entries[0].1 < entries[1].1);
1203312051

12034-
cache.put(&key3, executor.clone());
12052+
cache.put(&[(&key3, executor.clone())]);
1203512053
assert!(cache.get(&entries[0].0).is_none());
1203612054
assert!(cache.get(&entries[1].0).is_some());
1203712055
}

0 commit comments

Comments
 (0)