remove hashmap from stake_history (#5834)

This commit is contained in:
Rob Walker 2019-09-07 10:33:06 -07:00 committed by GitHub
parent bdda79343e
commit affcb5ec43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 37 deletions

View File

@ -20,10 +20,7 @@ crate::solana_name_id!(ID, "SysvarS1otHashes111111111111111111111111111");
pub const MAX_SLOT_HASHES: usize = 512; // 512 slots to get your vote in
#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct SlotHashes {
// non-pub to keep control of size
inner: Vec<(Slot, Hash)>,
}
pub struct SlotHashes(Vec<(Slot, Hash)>);
impl SlotHashes {
pub fn from(account: &Account) -> Option<Self> {
@ -34,26 +31,30 @@ impl SlotHashes {
}
pub fn size_of() -> usize {
serialized_size(&SlotHashes {
inner: vec![(0, Hash::default()); MAX_SLOT_HASHES],
})
.unwrap() as usize
serialized_size(&SlotHashes(vec![(0, Hash::default()); MAX_SLOT_HASHES])).unwrap() as usize
}
pub fn add(&mut self, slot: Slot, hash: Hash) {
self.inner.insert(0, (slot, hash));
self.inner.truncate(MAX_SLOT_HASHES);
match self.binary_search_by(|probe| slot.cmp(&probe.0)) {
Ok(index) => (self.0)[index] = (slot, hash),
Err(index) => (self.0).insert(index, (slot, hash)),
}
(self.0).truncate(MAX_SLOT_HASHES);
}
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn get(&self, slot: &Slot) -> Option<&Hash> {
self.binary_search_by(|probe| slot.cmp(&probe.0))
.ok()
.map(|index| &self[index].1)
}
pub fn new(slot_hashes: &[(Slot, Hash)]) -> Self {
Self {
inner: slot_hashes.to_vec(),
}
Self(slot_hashes.to_vec())
}
}
impl Deref for SlotHashes {
type Target = Vec<(u64, Hash)>;
fn deref(&self) -> &Self::Target {
&self.inner
&self.0
}
}
@ -83,7 +84,7 @@ mod tests {
let account = create_account(lamports, &[]);
assert_eq!(account.data.len(), SlotHashes::size_of());
let slot_hashes = SlotHashes::from(&account);
assert_eq!(slot_hashes, Some(SlotHashes { inner: vec![] }));
assert_eq!(slot_hashes, Some(SlotHashes(vec![])));
let mut slot_hashes = slot_hashes.unwrap();
for i in 0..MAX_SLOT_HASHES + 1 {
slot_hashes.add(

View File

@ -2,13 +2,10 @@
//!
//! this account carries history about stake activations and de-activations
//!
use crate::account::Account;
use crate::sysvar;
use bincode::serialized_size;
use std::collections::HashMap;
use std::ops::Deref;
pub use crate::clock::Epoch;
use crate::{account::Account, sysvar};
use bincode::serialized_size;
use std::ops::Deref;
const ID: [u8; 32] = [
6, 167, 213, 23, 25, 53, 132, 208, 254, 237, 155, 179, 67, 29, 19, 32, 107, 229, 68, 40, 27,
@ -27,9 +24,7 @@ pub struct StakeHistoryEntry {
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)]
pub struct StakeHistory {
inner: HashMap<Epoch, StakeHistoryEntry>,
}
pub struct StakeHistory(Vec<(Epoch, StakeHistoryEntry)>);
impl StakeHistory {
pub fn from(account: &Account) -> Option<Self> {
@ -40,27 +35,33 @@ impl StakeHistory {
}
pub fn size_of() -> usize {
serialized_size(
&(0..MAX_STAKE_HISTORY)
.map(|i| (i as u64, StakeHistoryEntry::default()))
.collect::<HashMap<_, _>>(),
)
serialized_size(&StakeHistory(vec![
(0, StakeHistoryEntry::default());
MAX_STAKE_HISTORY
]))
.unwrap() as usize
}
pub fn add(&mut self, epoch: Epoch, entry: StakeHistoryEntry) {
self.inner.insert(epoch, entry);
if self.len() > MAX_STAKE_HISTORY {
let oldest = *self.inner.keys().min().unwrap();
self.inner.remove(&oldest);
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn get(&self, epoch: &Epoch) -> Option<&StakeHistoryEntry> {
self.binary_search_by(|probe| epoch.cmp(&probe.0))
.ok()
.map(|index| &self[index].1)
}
pub fn add(&mut self, epoch: Epoch, entry: StakeHistoryEntry) {
match self.binary_search_by(|probe| epoch.cmp(&probe.0)) {
Ok(index) => (self.0)[index] = (epoch, entry),
Err(index) => (self.0).insert(index, (epoch, entry)),
}
(self.0).truncate(MAX_STAKE_HISTORY);
}
}
impl Deref for StakeHistory {
type Target = HashMap<Epoch, StakeHistoryEntry>;
type Target = Vec<(Epoch, StakeHistoryEntry)>;
fn deref(&self) -> &Self::Target {
&self.inner
&self.0
}
}
@ -103,7 +104,15 @@ mod tests {
);
}
assert_eq!(stake_history.len(), MAX_STAKE_HISTORY);
assert_eq!(*stake_history.keys().min().unwrap(), 1);
assert_eq!(stake_history.iter().map(|entry| entry.0).min().unwrap(), 1);
assert_eq!(stake_history.get(&0), None);
assert_eq!(
stake_history.get(&1),
Some(&StakeHistoryEntry {
activating: 1,
..StakeHistoryEntry::default()
})
);
// verify the account can hold a full instance
assert_eq!(
StakeHistory::from(&create_account(lamports, &stake_history)),