Perf: Store deserialized sysvars in the sysvars cache (backport #22455) (#22480)

* Perf: Store deserialized sysvars in the sysvars cache (#22455)

* Perf: Store deserialized sysvars in sysvars cache

* add bench

* resolve conflicts

Co-authored-by: Justin Starry <justin@solana.com>
This commit is contained in:
mergify[bot]
2022-01-15 08:48:34 +00:00
committed by GitHub
parent e121b94524
commit 4079f12a3e
11 changed files with 388 additions and 171 deletions

View File

@ -27,7 +27,6 @@ use {
pubkey::Pubkey,
rent::Rent,
saturating_add_assign,
sysvar::Sysvar,
},
std::{borrow::Cow, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc, sync::Arc},
};
@ -951,21 +950,9 @@ impl<'a> InvokeContext<'a> {
&self.current_compute_budget
}
/// Get the value of a sysvar by its id
pub fn get_sysvar<T: Sysvar>(&self, id: &Pubkey) -> Result<T, InstructionError> {
self.sysvar_cache
.iter()
.find_map(|(key, data)| {
if id == key {
bincode::deserialize(data).ok()
} else {
None
}
})
.ok_or_else(|| {
ic_msg!(self, "Unable to get sysvar {}", id);
InstructionError::UnsupportedSysvar
})
/// Get cached sysvars
pub fn get_sysvar_cache(&self) -> &SysvarCache {
&self.sysvar_cache
}
}

View File

@ -1,9 +1,13 @@
#[allow(deprecated)]
use solana_sdk::sysvar::fees::Fees;
use {
solana_sdk::{
account::{AccountSharedData, ReadableAccount},
pubkey::Pubkey,
instruction::InstructionError,
sysvar::{
clock::Clock, epoch_schedule::EpochSchedule, rent::Rent, slot_hashes::SlotHashes,
},
},
std::ops::Deref,
std::sync::Arc,
};
#[cfg(RUSTC_WITH_SPECIALIZATION)]
@ -15,25 +19,63 @@ impl ::solana_frozen_abi::abi_example::AbiExample for SysvarCache {
}
#[derive(Default, Clone, Debug)]
pub struct SysvarCache(Vec<(Pubkey, Vec<u8>)>);
impl Deref for SysvarCache {
type Target = Vec<(Pubkey, Vec<u8>)>;
fn deref(&self) -> &Self::Target {
&self.0
}
pub struct SysvarCache {
clock: Option<Arc<Clock>>,
epoch_schedule: Option<Arc<EpochSchedule>>,
#[allow(deprecated)]
fees: Option<Arc<Fees>>,
rent: Option<Arc<Rent>>,
slot_hashes: Option<Arc<SlotHashes>>,
}
impl SysvarCache {
pub fn push_entry(&mut self, pubkey: Pubkey, data: Vec<u8>) {
self.0.push((pubkey, data));
pub fn get_clock(&self) -> Result<Arc<Clock>, InstructionError> {
self.clock
.clone()
.ok_or(InstructionError::UnsupportedSysvar)
}
pub fn update_entry(&mut self, pubkey: &Pubkey, new_account: &AccountSharedData) {
if let Some(position) = self.iter().position(|(id, _data)| id == pubkey) {
self.0[position].1 = new_account.data().to_vec();
} else {
self.0.push((*pubkey, new_account.data().to_vec()));
}
pub fn set_clock(&mut self, clock: Clock) {
self.clock = Some(Arc::new(clock));
}
pub fn get_epoch_schedule(&self) -> Result<Arc<EpochSchedule>, InstructionError> {
self.epoch_schedule
.clone()
.ok_or(InstructionError::UnsupportedSysvar)
}
pub fn set_epoch_schedule(&mut self, epoch_schedule: EpochSchedule) {
self.epoch_schedule = Some(Arc::new(epoch_schedule));
}
#[deprecated]
#[allow(deprecated)]
pub fn get_fees(&self) -> Result<Arc<Fees>, InstructionError> {
self.fees.clone().ok_or(InstructionError::UnsupportedSysvar)
}
#[deprecated]
#[allow(deprecated)]
pub fn set_fees(&mut self, fees: Fees) {
self.fees = Some(Arc::new(fees));
}
pub fn get_rent(&self) -> Result<Arc<Rent>, InstructionError> {
self.rent.clone().ok_or(InstructionError::UnsupportedSysvar)
}
pub fn set_rent(&mut self, rent: Rent) {
self.rent = Some(Arc::new(rent));
}
pub fn get_slot_hashes(&self) -> Result<Arc<SlotHashes>, InstructionError> {
self.slot_hashes
.clone()
.ok_or(InstructionError::UnsupportedSysvar)
}
pub fn set_slot_hashes(&mut self, slot_hashes: SlotHashes) {
self.slot_hashes = Some(Arc::new(slot_hashes));
}
}