Skip to content

Commit

Permalink
Stop caching sysvars, instead load them ahead of time (backport #21108)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstarry committed Jan 19, 2022
1 parent 42c3fbc commit 28d8608
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 167 deletions.
29 changes: 8 additions & 21 deletions program-test/src/lib.rs
Expand Up @@ -33,7 +33,7 @@ use {
native_token::sol_to_lamports,
poh_config::PohConfig,
process_instruction::{
stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext,
self, stable_log, BpfComputeBudget, InvokeContext, ProcessInstructionWithContext,
},
program_error::{ProgramError, ACCOUNT_BORROW_FAILED, UNSUPPORTED_SYSVAR},
pubkey::Pubkey,
Expand Down Expand Up @@ -197,24 +197,6 @@ fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
var_addr: *mut u8,
) -> u64 {
let invoke_context = get_invoke_context();

let sysvar_data = match invoke_context.get_sysvar_data(id).ok_or_else(|| {
ic_msg!(invoke_context, "Unable to get Sysvar {}", id);
UNSUPPORTED_SYSVAR
}) {
Ok(sysvar_data) => sysvar_data,
Err(err) => return err,
};

let var: T = match bincode::deserialize(&sysvar_data) {
Ok(sysvar_data) => sysvar_data,
Err(_) => return UNSUPPORTED_SYSVAR,
};

unsafe {
*(var_addr as *mut _ as *mut T) = var;
}

if invoke_context
.get_compute_meter()
.try_borrow_mut()
Expand All @@ -225,8 +207,13 @@ fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
{
panic!("Exceeded compute budget");
}

SUCCESS
match process_instruction::get_sysvar::<T>(invoke_context, id) {
Ok(sysvar_data) => unsafe {
*(var_addr as *mut _ as *mut T) = sysvar_data;
SUCCESS
},
Err(_) => UNSUPPORTED_SYSVAR,
}
}

struct SyscallStubs {}
Expand Down
16 changes: 4 additions & 12 deletions programs/bpf_loader/src/syscalls.rs
Expand Up @@ -3650,9 +3650,7 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(vec![]);
let mut data = vec![];
bincode::serialize_into(&mut data, &src_clock).unwrap();
invoke_context
.sysvars
.push((sysvar::clock::id(), Some(Rc::new(data))));
invoke_context.sysvars = vec![(sysvar::clock::id(), data)];

let mut syscall = SyscallGetClockSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down Expand Up @@ -3695,9 +3693,7 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(vec![]);
let mut data = vec![];
bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
invoke_context
.sysvars
.push((sysvar::epoch_schedule::id(), Some(Rc::new(data))));
invoke_context.sysvars = vec![(sysvar::epoch_schedule::id(), data)];

let mut syscall = SyscallGetEpochScheduleSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down Expand Up @@ -3746,9 +3742,7 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(vec![]);
let mut data = vec![];
bincode::serialize_into(&mut data, &src_fees).unwrap();
invoke_context
.sysvars
.push((sysvar::fees::id(), Some(Rc::new(data))));
invoke_context.sysvars = vec![(sysvar::fees::id(), data)];

let mut syscall = SyscallGetFeesSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down Expand Up @@ -3789,9 +3783,7 @@ mod tests {
let mut invoke_context = MockInvokeContext::new(vec![]);
let mut data = vec![];
bincode::serialize_into(&mut data, &src_rent).unwrap();
invoke_context
.sysvars
.push((sysvar::rent::id(), Some(Rc::new(data))));
invoke_context.sysvars = vec![(sysvar::rent::id(), data)];

let mut syscall = SyscallGetRentSysvar {
invoke_context: Rc::new(RefCell::new(&mut invoke_context)),
Expand Down
24 changes: 9 additions & 15 deletions programs/stake/src/stake_instruction.rs
Expand Up @@ -281,16 +281,16 @@ mod tests {
account::{self, Account, AccountSharedData, WritableAccount},
instruction::{AccountMeta, Instruction},
keyed_account::KeyedAccount,
process_instruction::{mock_set_sysvar, MockInvokeContext},
process_instruction::MockInvokeContext,
rent::Rent,
stake::{
config as stake_config,
instruction::{self, LockupArgs},
state::{Authorized, Lockup, StakeAuthorize},
},
sysvar::stake_history::StakeHistory,
sysvar::{stake_history::StakeHistory, Sysvar},
},
std::{cell::RefCell, rc::Rc, str::FromStr},
std::{cell::RefCell, str::FromStr},
};

fn create_default_account() -> RefCell<AccountSharedData> {
Expand Down Expand Up @@ -370,12 +370,9 @@ mod tests {
.collect();

let mut invoke_context = MockInvokeContext::new(keyed_accounts);
mock_set_sysvar(
&mut invoke_context,
sysvar::clock::id(),
sysvar::clock::Clock::default(),
)
.unwrap();
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
invoke_context.sysvars = vec![(sysvar::clock::id(), data)];
super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context)
}
}
Expand Down Expand Up @@ -1038,12 +1035,9 @@ mod tests {
];

let mut invoke_context = MockInvokeContext::new(keyed_accounts);
let clock = Clock::default();
let mut data = vec![];
bincode::serialize_into(&mut data, &clock).unwrap();
invoke_context
.sysvars
.push((sysvar::clock::id(), Some(Rc::new(data))));
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
invoke_context.sysvars = vec![(sysvar::clock::id(), data)];

assert_eq!(
super::process_instruction(
Expand Down
12 changes: 5 additions & 7 deletions programs/vote/src/vote_instruction.rs
Expand Up @@ -402,8 +402,9 @@ mod tests {
bincode::serialize,
solana_sdk::{
account::{self, Account, AccountSharedData},
process_instruction::{mock_set_sysvar, MockInvokeContext},
process_instruction::MockInvokeContext,
rent::Rent,
sysvar::Sysvar,
},
std::{cell::RefCell, str::FromStr},
};
Expand Down Expand Up @@ -462,12 +463,9 @@ mod tests {
.map(|(meta, account)| KeyedAccount::new(&meta.pubkey, meta.is_signer, account))
.collect();
let mut invoke_context = MockInvokeContext::new(keyed_accounts);
mock_set_sysvar(
&mut invoke_context,
sysvar::rent::id(),
sysvar::rent::Rent::default(),
)
.unwrap();
let mut data = Vec::with_capacity(sysvar::rent::Rent::size_of());
bincode::serialize_into(&mut data, &sysvar::rent::Rent::default()).unwrap();
invoke_context.sysvars = vec![(sysvar::rent::id(), data)];
super::process_instruction(&Pubkey::default(), &instruction.data, &mut invoke_context)
}
}
Expand Down
28 changes: 26 additions & 2 deletions runtime/src/bank.rs
Expand Up @@ -1158,6 +1158,8 @@ pub struct Bank {
vote_only_bank: bool,

pub cost_tracker: RwLock<CostTracker>,

sysvar_cache: RwLock<Vec<(Pubkey, Vec<u8>)>>,
}

impl Default for BlockhashQueue {
Expand Down Expand Up @@ -1290,6 +1292,7 @@ impl Bank {
bank.update_rent();
bank.update_epoch_schedule();
bank.update_recent_blockhashes();
bank.fill_sysvar_cache();
bank
}

Expand Down Expand Up @@ -1430,6 +1433,7 @@ impl Bank {
)),
freeze_started: AtomicBool::new(false),
cost_tracker: RwLock::new(CostTracker::default()),
sysvar_cache: RwLock::new(Vec::new()),
};

let mut ancestors = Vec::with_capacity(1 + new.parents().len());
Expand Down Expand Up @@ -1471,6 +1475,7 @@ impl Bank {
if !new.fix_recent_blockhashes_sysvar_delay() {
new.update_recent_blockhashes();
}
new.fill_sysvar_cache();

time.stop();

Expand Down Expand Up @@ -1605,6 +1610,7 @@ impl Bank {
freeze_started: AtomicBool::new(fields.hash != Hash::default()),
vote_only_bank: false,
cost_tracker: RwLock::new(CostTracker::default()),
sysvar_cache: RwLock::new(Vec::new()),
};
bank.finish_init(
genesis_config,
Expand Down Expand Up @@ -1780,6 +1786,14 @@ impl Bank {
}

self.store_account_and_update_capitalization(pubkey, &new_account);

// Update the entry in the cache
let mut sysvar_cache = self.sysvar_cache.write().unwrap();
if let Some(position) = sysvar_cache.iter().position(|(id, _data)| id == pubkey) {
sysvar_cache[position].1 = new_account.data().to_vec();
} else {
sysvar_cache.push((*pubkey, new_account.data().to_vec()));
}
}

fn inherit_specially_retained_account_fields(
Expand Down Expand Up @@ -1917,6 +1931,17 @@ impl Bank {
});
}

fn fill_sysvar_cache(&mut self) {
let mut sysvar_cache = self.sysvar_cache.write().unwrap();
for id in sysvar::ALL_IDS.iter() {
if !sysvar_cache.iter().any(|(key, _data)| key == id) {
if let Some(account) = self.get_account_with_fixed_root(id) {
sysvar_cache.push((*id, account.data().to_vec()));
}
}
}
}

pub fn get_slot_history(&self) -> SlotHistory {
from_account(&self.get_account(&sysvar::slot_history::id()).unwrap()).unwrap()
}
Expand Down Expand Up @@ -3587,8 +3612,7 @@ impl Bank {
bpf_compute_budget,
compute_meter,
timings,
self.rc.accounts.clone(),
&self.ancestors,
&*self.sysvar_cache.read().unwrap(),
);
process_message_time.stop();
saturating_add_assign!(
Expand Down

0 comments on commit 28d8608

Please sign in to comment.