Skip to content

Commit

Permalink
Stop caching sysvars, instead load them ahead of time.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lichtso committed Nov 1, 2021
1 parent ef6f40e commit 19d85e6
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 88 deletions.
8 changes: 4 additions & 4 deletions programs/bpf_loader/src/syscalls.rs
Expand Up @@ -3287,7 +3287,7 @@ mod tests {
invoke_context
.get_sysvars()
.borrow_mut()
.push((sysvar::clock::id(), Some(Rc::new(data))));
.push((sysvar::clock::id(), data));

let mut syscall = SyscallGetClockSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down Expand Up @@ -3333,7 +3333,7 @@ mod tests {
invoke_context
.get_sysvars()
.borrow_mut()
.push((sysvar::epoch_schedule::id(), Some(Rc::new(data))));
.push((sysvar::epoch_schedule::id(), data));

let mut syscall = SyscallGetEpochScheduleSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down Expand Up @@ -3386,7 +3386,7 @@ mod tests {
invoke_context
.get_sysvars()
.borrow_mut()
.push((sysvar::fees::id(), Some(Rc::new(data))));
.push((sysvar::fees::id(), data));

let mut syscall = SyscallGetFeesSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down Expand Up @@ -3430,7 +3430,7 @@ mod tests {
invoke_context
.get_sysvars()
.borrow_mut()
.push((sysvar::rent::id(), Some(Rc::new(data))));
.push((sysvar::rent::id(), data));

let mut syscall = SyscallGetRentSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down
6 changes: 3 additions & 3 deletions programs/stake/src/stake_instruction.rs
Expand Up @@ -340,7 +340,7 @@ mod tests {
},
sysvar::{stake_history::StakeHistory, Sysvar},
};
use std::{cell::RefCell, rc::Rc, str::FromStr};
use std::{cell::RefCell, str::FromStr};

fn create_default_account() -> RefCell<AccountSharedData> {
RefCell::new(AccountSharedData::default())
Expand Down Expand Up @@ -447,7 +447,7 @@ mod tests {
invoke_context
.get_sysvars()
.borrow_mut()
.push((sysvar::clock::id(), Some(Rc::new(data))));
.push((sysvar::clock::id(), data));
super::process_instruction(1, &instruction.data, &mut invoke_context)
}
}
Expand Down Expand Up @@ -1105,7 +1105,7 @@ mod tests {
invoke_context
.get_sysvars()
.borrow_mut()
.push((sysvar::clock::id(), Some(Rc::new(data))));
.push((sysvar::clock::id(), data));

assert_eq!(
super::process_instruction(
Expand Down
10 changes: 8 additions & 2 deletions runtime/src/bank.rs
Expand Up @@ -3776,6 +3776,13 @@ impl Bank {
&self.rent_collector,
&self.feature_set,
);
let sysvars = Rc::new(RefCell::new(
self.get_program_accounts(&sysvar::id())
.unwrap_or_else(|_| Vec::new())
.into_iter()
.map(|(id, account)| (id, account.data().to_vec()))
.collect(),
));
load_time.stop();

let mut execution_time = Measure::start("execution_time");
Expand Down Expand Up @@ -3860,8 +3867,7 @@ impl Bank {
compute_budget,
compute_meter,
&mut timings.details,
self.rc.accounts.clone(),
&self.ancestors,
sysvars.clone(),
blockhash,
lamports_per_signature,
);
Expand Down
74 changes: 17 additions & 57 deletions runtime/src/message_processor.rs
@@ -1,6 +1,6 @@
use crate::{
accounts::Accounts, ancestors::Ancestors, instruction_recorder::InstructionRecorder,
log_collector::LogCollector, rent_collector::RentCollector,
instruction_recorder::InstructionRecorder, log_collector::LogCollector,
rent_collector::RentCollector,
};
use log::*;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -87,10 +87,8 @@ pub struct ThisInvokeContext<'a> {
instruction_recorders: Option<&'a [InstructionRecorder]>,
feature_set: Arc<FeatureSet>,
pub timings: ExecuteDetailsTimings,
account_db: Arc<Accounts>,
ancestors: Option<&'a Ancestors>,
#[allow(clippy::type_complexity)]
sysvars: RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>>,
sysvars: Rc<RefCell<Vec<(Pubkey, Vec<u8>)>>>,
blockhash: Hash,
lamports_per_signature: u64,
return_data: (Pubkey, Vec<u8>),
Expand All @@ -107,8 +105,7 @@ impl<'a> ThisInvokeContext<'a> {
executors: Rc<RefCell<Executors>>,
instruction_recorders: Option<&'a [InstructionRecorder]>,
feature_set: Arc<FeatureSet>,
account_db: Arc<Accounts>,
ancestors: Option<&'a Ancestors>,
sysvars: Rc<RefCell<Vec<(Pubkey, Vec<u8>)>>>,
blockhash: Hash,
lamports_per_signature: u64,
) -> Self {
Expand All @@ -126,9 +123,7 @@ impl<'a> ThisInvokeContext<'a> {
instruction_recorders,
feature_set,
timings: ExecuteDetailsTimings::default(),
account_db,
ancestors,
sysvars: RefCell::new(Vec::new()),
sysvars,
blockhash,
lamports_per_signature,
return_data: (Pubkey::default(), Vec::new()),
Expand All @@ -150,8 +145,7 @@ impl<'a> ThisInvokeContext<'a> {
Rc::new(RefCell::new(Executors::default())),
None,
feature_set,
Arc::new(Accounts::default_for_tests()),
None,
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
)
Expand Down Expand Up @@ -453,30 +447,8 @@ impl<'a> InvokeContext for ThisInvokeContext<'a> {
self.timings.deserialize_us += deserialize_us;
}
#[allow(clippy::type_complexity)]
fn get_sysvars(&self) -> &RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>> {
&self.sysvars
}
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>> {
if let Ok(mut sysvars) = self.sysvars.try_borrow_mut() {
// Try share from cache
let mut result = sysvars
.iter()
.find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None });
if result.is_none() {
if let Some(ancestors) = self.ancestors {
// Load it
result = self
.account_db
.load_with_fixed_root(ancestors, id)
.map(|(account, _)| Rc::new(account.data().to_vec()));
// Cache it
sysvars.push((*id, result.clone()));
}
}
result
} else {
None
}
fn get_sysvars(&self) -> Rc<RefCell<Vec<(Pubkey, Vec<u8>)>>> {
self.sysvars.clone()
}
fn get_compute_budget(&self) -> &ComputeBudget {
&self.compute_budget
Expand Down Expand Up @@ -618,8 +590,7 @@ impl MessageProcessor {
compute_budget: ComputeBudget,
compute_meter: Rc<RefCell<dyn ComputeMeter>>,
timings: &mut ExecuteDetailsTimings,
account_db: Arc<Accounts>,
ancestors: &Ancestors,
sysvars: Rc<RefCell<Vec<(Pubkey, Vec<u8>)>>>,
blockhash: Hash,
lamports_per_signature: u64,
) -> Result<(), TransactionError> {
Expand All @@ -633,8 +604,7 @@ impl MessageProcessor {
executors,
instruction_recorders,
feature_set,
account_db,
Some(ancestors),
sysvars,
blockhash,
lamports_per_signature,
);
Expand Down Expand Up @@ -979,7 +949,6 @@ mod tests {
let program_indices = vec![vec![2]];

let executors = Rc::new(RefCell::new(Executors::default()));
let ancestors = Ancestors::default();

let account_metas = vec![
AccountMeta::new(accounts[0].0, true),
Expand Down Expand Up @@ -1007,8 +976,7 @@ mod tests {
ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()),
&ancestors,
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
);
Expand Down Expand Up @@ -1038,8 +1006,7 @@ mod tests {
ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()),
&ancestors,
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
);
Expand Down Expand Up @@ -1073,8 +1040,7 @@ mod tests {
ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()),
&ancestors,
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
);
Expand Down Expand Up @@ -1188,7 +1154,6 @@ mod tests {
let program_indices = vec![vec![2]];

let executors = Rc::new(RefCell::new(Executors::default()));
let ancestors = Ancestors::default();

let account_metas = vec![
AccountMeta::new(accounts[0].0, true),
Expand Down Expand Up @@ -1218,8 +1183,7 @@ mod tests {
ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()),
&ancestors,
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
);
Expand Down Expand Up @@ -1253,8 +1217,7 @@ mod tests {
ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()),
&ancestors,
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
);
Expand All @@ -1272,7 +1235,6 @@ mod tests {
)],
Some(&accounts[0].0),
);
let ancestors = Ancestors::default();
let result = MessageProcessor::process_message(
&instruction_processor,
&message,
Expand All @@ -1286,8 +1248,7 @@ mod tests {
ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()),
&ancestors,
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
);
Expand Down Expand Up @@ -1578,8 +1539,7 @@ mod tests {
ComputeBudget::new(),
ThisComputeMeter::new_ref(std::i64::MAX as u64),
&mut ExecuteDetailsTimings::default(),
Arc::new(Accounts::default_for_tests()),
&Ancestors::default(),
Rc::new(RefCell::new(Vec::new())),
Hash::default(),
0,
);
Expand Down
42 changes: 20 additions & 22 deletions sdk/src/process_instruction.rs
Expand Up @@ -122,9 +122,7 @@ pub trait InvokeContext {
);
/// Get sysvars
#[allow(clippy::type_complexity)]
fn get_sysvars(&self) -> &RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>>;
/// Get sysvar data
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>>;
fn get_sysvars(&self) -> Rc<RefCell<Vec<(Pubkey, Vec<u8>)>>>;
/// Get this invocation's compute budget
fn get_compute_budget(&self) -> &ComputeBudget;
/// Set this invocation's blockhash
Expand Down Expand Up @@ -175,15 +173,21 @@ pub fn get_sysvar<T: Sysvar>(
invoke_context: &dyn InvokeContext,
id: &Pubkey,
) -> Result<T, InstructionError> {
let sysvar_data = invoke_context.get_sysvar_data(id).ok_or_else(|| {
ic_msg!(invoke_context, "Unable to get sysvar {}", id);
InstructionError::UnsupportedSysvar
})?;

bincode::deserialize(&sysvar_data).map_err(|err| {
ic_msg!(invoke_context, "Unable to get sysvar {}: {:?}", id, err);
InstructionError::UnsupportedSysvar
})
invoke_context
.get_sysvars()
.borrow()
.iter()
.find_map(|(key, data)| {
if id == key {
bincode::deserialize(data).ok()
} else {
None
}
})
.ok_or_else(|| {
ic_msg!(invoke_context, "Unable to get sysvar {}", id);
InstructionError::UnsupportedSysvar
})
}

/// Compute meter
Expand Down Expand Up @@ -357,7 +361,7 @@ pub struct MockInvokeContext<'a> {
pub programs: Vec<(Pubkey, ProcessInstructionWithContext)>,
pub accounts: Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>,
#[allow(clippy::type_complexity)]
pub sysvars: RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>>,
pub sysvars: Rc<RefCell<Vec<(Pubkey, Vec<u8>)>>>,
pub disabled_features: HashSet<Pubkey>,
pub blockhash: Hash,
pub lamports_per_signature: u64,
Expand All @@ -376,7 +380,7 @@ impl<'a> MockInvokeContext<'a> {
})),
programs: vec![],
accounts: vec![],
sysvars: RefCell::new(Vec::new()),
sysvars: Rc::new(RefCell::new(Vec::new())),
disabled_features: HashSet::default(),
blockhash: Hash::default(),
lamports_per_signature: 0,
Expand Down Expand Up @@ -491,14 +495,8 @@ impl<'a> InvokeContext for MockInvokeContext<'a> {
) {
}
#[allow(clippy::type_complexity)]
fn get_sysvars(&self) -> &RefCell<Vec<(Pubkey, Option<Rc<Vec<u8>>>)>> {
&self.sysvars
}
fn get_sysvar_data(&self, id: &Pubkey) -> Option<Rc<Vec<u8>>> {
self.sysvars
.borrow()
.iter()
.find_map(|(key, sysvar)| if id == key { sysvar.clone() } else { None })
fn get_sysvars(&self) -> Rc<RefCell<Vec<(Pubkey, Vec<u8>)>>> {
self.sysvars.clone()
}
fn get_compute_budget(&self) -> &ComputeBudget {
&self.compute_budget
Expand Down

0 comments on commit 19d85e6

Please sign in to comment.