cache executors on failed transactions (#22308)
This commit is contained in:
@ -65,31 +65,56 @@ pub trait Executor: Debug + Send + Sync {
|
||||
|
||||
pub type Executors = HashMap<Pubkey, TransactionExecutor>;
|
||||
|
||||
/// Tracks whether a given executor is "dirty" and needs to
|
||||
/// updated in the executors cache
|
||||
/// Tracks whether a given executor is "dirty" and needs to updated in the
|
||||
/// executors cache
|
||||
pub struct TransactionExecutor {
|
||||
pub executor: Arc<dyn Executor>,
|
||||
pub is_dirty: bool,
|
||||
executor: Arc<dyn Executor>,
|
||||
is_miss: bool,
|
||||
is_updated: bool,
|
||||
}
|
||||
|
||||
impl TransactionExecutor {
|
||||
/// Wraps an executor and tracks that it doesn't need
|
||||
/// to be updated in the executors cache.
|
||||
pub fn cached(executor: Arc<dyn Executor>) -> Self {
|
||||
/// Wraps an executor and tracks that it doesn't need to be updated in the
|
||||
/// executors cache.
|
||||
pub fn new_cached(executor: Arc<dyn Executor>) -> Self {
|
||||
Self {
|
||||
executor,
|
||||
is_dirty: false,
|
||||
is_miss: false,
|
||||
is_updated: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps an executor and tracks that it needs to be
|
||||
/// updated in the executors cache.
|
||||
pub fn dirty(executor: Arc<dyn Executor>) -> Self {
|
||||
/// Wraps an executor and tracks that it needs to be updated in the
|
||||
/// executors cache.
|
||||
pub fn new_miss(executor: Arc<dyn Executor>) -> Self {
|
||||
Self {
|
||||
executor,
|
||||
is_dirty: true,
|
||||
is_miss: true,
|
||||
is_updated: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps an executor and tracks that it needs to be updated in the
|
||||
/// executors cache only if the transaction succeeded.
|
||||
pub fn new_updated(executor: Arc<dyn Executor>) -> Self {
|
||||
Self {
|
||||
executor,
|
||||
is_miss: false,
|
||||
is_updated: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_dirty(&self, include_updates: bool) -> bool {
|
||||
self.is_miss || (include_updates && self.is_updated)
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Arc<dyn Executor> {
|
||||
self.executor.clone()
|
||||
}
|
||||
|
||||
pub fn clear_miss_for_test(&mut self) {
|
||||
self.is_miss = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute meter
|
||||
@ -894,12 +919,18 @@ impl<'a> InvokeContext<'a> {
|
||||
&self.accounts_data_meter
|
||||
}
|
||||
|
||||
/// Loaders may need to do work in order to execute a program. Cache
|
||||
/// the work that can be re-used across executions
|
||||
/// Cache an executor that wasn't found in the cache
|
||||
pub fn add_executor(&self, pubkey: &Pubkey, executor: Arc<dyn Executor>) {
|
||||
self.executors
|
||||
.borrow_mut()
|
||||
.insert(*pubkey, TransactionExecutor::dirty(executor));
|
||||
.insert(*pubkey, TransactionExecutor::new_miss(executor));
|
||||
}
|
||||
|
||||
/// Cache an executor that has changed
|
||||
pub fn update_executor(&self, pubkey: &Pubkey, executor: Arc<dyn Executor>) {
|
||||
self.executors
|
||||
.borrow_mut()
|
||||
.insert(*pubkey, TransactionExecutor::new_updated(executor));
|
||||
}
|
||||
|
||||
/// Get the completed loader work that can be re-used across execution
|
||||
|
Reference in New Issue
Block a user