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

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

* resolve conflicts

* remove bench
This commit is contained in:
Justin Starry
2022-01-22 14:09:05 +08:00
committed by GitHub
parent f3126f7e77
commit 4b7450e89e
9 changed files with 321 additions and 153 deletions

View File

@@ -7,7 +7,6 @@ use {
instruction::{CompiledInstruction, Instruction, InstructionError},
keyed_account::{create_keyed_accounts_unified, KeyedAccount},
pubkey::Pubkey,
sysvar::Sysvar,
},
std::{borrow::Cow, cell::RefCell, collections::HashSet, fmt::Debug, rc::Rc, sync::Arc},
};
@@ -145,26 +144,6 @@ macro_rules! ic_msg {
};
}
pub fn get_sysvar<T: Sysvar>(
invoke_context: &dyn InvokeContext,
id: &Pubkey,
) -> Result<T, InstructionError> {
invoke_context
.get_sysvar_cache()
.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
})
}
#[derive(Clone, Copy, Debug, AbiExample, PartialEq)]
pub struct BpfComputeBudget {
/// Number of compute units that an instruction is allowed. Compute units

View File

@@ -1,9 +1,12 @@
use {
solana_sdk::{
account::{AccountSharedData, ReadableAccount},
pubkey::Pubkey,
instruction::InstructionError,
sysvar::{
clock::Clock, epoch_schedule::EpochSchedule, fees::Fees, rent::Rent,
slot_hashes::SlotHashes,
},
},
std::ops::Deref,
std::sync::Arc,
};
#[cfg(RUSTC_WITH_SPECIALIZATION)]
@@ -15,25 +18,58 @@ 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>>,
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));
}
pub fn get_fees(&self) -> Result<Arc<Fees>, InstructionError> {
self.fees.clone().ok_or(InstructionError::UnsupportedSysvar)
}
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));
}
}