@@ -443,13 +443,23 @@ impl CachedExecutors {
443
443
})
444
444
}
445
445
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() {
453
463
let mut counts = self
454
464
.executors
455
465
.iter()
@@ -460,10 +470,15 @@ impl CachedExecutors {
460
470
.collect::<Vec<_>>();
461
471
counts.sort_unstable_by_key(|(_, count)| *count);
462
472
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 ());
464
474
465
475
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(..) {
467
482
let _ = self.executors.remove(&least_key);
468
483
self.stats
469
484
.evictions
@@ -473,13 +488,15 @@ impl CachedExecutors {
473
488
}
474
489
}
475
490
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);
480
498
}
481
- };
482
- let _ = self.executors.insert(*pubkey, entry);
499
+ }
483
500
}
484
501
485
502
fn remove(&mut self, pubkey: &Pubkey) {
@@ -512,10 +529,13 @@ impl CachedExecutors {
512
529
.unwrap_or(0)
513
530
}
514
531
515
- fn get_primer_count (counts: &[(&Pubkey, u64)]) -> u64 {
532
+ fn get_primer_counts (counts: &[(&Pubkey, u64)], num_counts: usize ) -> Vec< u64> {
516
533
let max_primer_count = Self::get_primer_count_upper_bound_inclusive(counts);
517
534
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<_>>()
519
539
}
520
540
}
521
541
@@ -3425,9 +3445,7 @@ impl Bank {
3425
3445
if !dirty_executors.is_empty() {
3426
3446
let mut cache = self.cached_executors.write().unwrap();
3427
3447
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);
3431
3449
}
3432
3450
}
3433
3451
@@ -11924,17 +11942,17 @@ pub(crate) mod tests {
11924
11942
let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
11925
11943
let mut cache = CachedExecutors::new(3, 0);
11926
11944
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())] );
11930
11948
assert!(cache.get(&key1).is_some());
11931
11949
assert!(cache.get(&key2).is_some());
11932
11950
assert!(cache.get(&key3).is_some());
11933
11951
11934
11952
assert!(cache.get(&key1).is_some());
11935
11953
assert!(cache.get(&key1).is_some());
11936
11954
assert!(cache.get(&key2).is_some());
11937
- cache.put(&key4, executor.clone());
11955
+ cache.put(&[(& key4, executor.clone())] );
11938
11956
assert!(cache.get(&key4).is_some());
11939
11957
let num_retained = [&key1, &key2, &key3]
11940
11958
.iter()
@@ -11946,7 +11964,7 @@ pub(crate) mod tests {
11946
11964
assert!(cache.get(&key4).is_some());
11947
11965
assert!(cache.get(&key4).is_some());
11948
11966
assert!(cache.get(&key4).is_some());
11949
- cache.put(&key3, executor.clone());
11967
+ cache.put(&[(& key3, executor.clone())] );
11950
11968
assert!(cache.get(&key3).is_some());
11951
11969
let num_retained = [&key1, &key2, &key4]
11952
11970
.iter()
@@ -11957,7 +11975,7 @@ pub(crate) mod tests {
11957
11975
}
11958
11976
11959
11977
#[test]
11960
- fn test_cached_executors_eviction () {
11978
+ fn test_cached_executor_eviction () {
11961
11979
let key1 = solana_sdk::pubkey::new_rand();
11962
11980
let key2 = solana_sdk::pubkey::new_rand();
11963
11981
let key3 = solana_sdk::pubkey::new_rand();
@@ -11966,9 +11984,9 @@ pub(crate) mod tests {
11966
11984
let mut cache = CachedExecutors::new(3, 0);
11967
11985
assert!(cache.current_epoch == 0);
11968
11986
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())] );
11972
11990
assert!(cache.get(&key1).is_some());
11973
11991
assert!(cache.get(&key1).is_some());
11974
11992
assert!(cache.get(&key1).is_some());
@@ -11979,7 +11997,7 @@ pub(crate) mod tests {
11979
11997
assert!(cache.get(&key2).is_some());
11980
11998
assert!(cache.get(&key2).is_some());
11981
11999
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())] );
11983
12001
11984
12002
assert!(cache.get(&key4).is_some());
11985
12003
let num_retained = [&key1, &key2, &key3]
@@ -11989,8 +12007,8 @@ pub(crate) mod tests {
11989
12007
.count();
11990
12008
assert_eq!(num_retained, 2);
11991
12009
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())] );
11994
12012
assert!(cache.get(&key1).is_some());
11995
12013
assert!(cache.get(&key3).is_some());
11996
12014
let num_retained = [&key2, &key4]
@@ -12003,7 +12021,7 @@ pub(crate) mod tests {
12003
12021
cache = cache.clone_with_epoch(2);
12004
12022
assert!(cache.current_epoch == 2);
12005
12023
12006
- Arc::make_mut(&mut cache).put(&key3, executor.clone());
12024
+ Arc::make_mut(&mut cache).put(&[(& key3, executor.clone())] );
12007
12025
assert!(cache.get(&key3).is_some());
12008
12026
}
12009
12027
@@ -12015,11 +12033,11 @@ pub(crate) mod tests {
12015
12033
let executor: Arc<dyn Executor> = Arc::new(TestExecutor {});
12016
12034
let mut cache = CachedExecutors::new(2, 0);
12017
12035
12018
- cache.put(&key1, executor.clone());
12036
+ cache.put(&[(& key1, executor.clone())] );
12019
12037
for _ in 0..5 {
12020
12038
let _ = cache.get(&key1);
12021
12039
}
12022
- cache.put(&key2, executor.clone());
12040
+ cache.put(&[(& key2, executor.clone())] );
12023
12041
// make key1's use-count for sure greater than key2's
12024
12042
let _ = cache.get(&key1);
12025
12043
@@ -12031,7 +12049,7 @@ pub(crate) mod tests {
12031
12049
entries.sort_by_key(|(_, v)| *v);
12032
12050
assert!(entries[0].1 < entries[1].1);
12033
12051
12034
- cache.put(&key3, executor.clone());
12052
+ cache.put(&[(& key3, executor.clone())] );
12035
12053
assert!(cache.get(&entries[0].0).is_none());
12036
12054
assert!(cache.get(&entries[1].0).is_some());
12037
12055
}
0 commit comments