Make StakeHistory clone-on-write (#21573)
This commit is contained in:
@ -49,6 +49,7 @@ pub mod snapshot_package;
|
|||||||
pub mod snapshot_utils;
|
pub mod snapshot_utils;
|
||||||
pub mod sorted_storages;
|
pub mod sorted_storages;
|
||||||
pub mod stake_delegations;
|
pub mod stake_delegations;
|
||||||
|
pub mod stake_history;
|
||||||
pub mod stake_weighted_timestamp;
|
pub mod stake_weighted_timestamp;
|
||||||
pub mod stakes;
|
pub mod stakes;
|
||||||
pub mod status_cache;
|
pub mod status_cache;
|
||||||
|
@ -312,7 +312,7 @@ mod test_bank_serialize {
|
|||||||
|
|
||||||
// This some what long test harness is required to freeze the ABI of
|
// This some what long test harness is required to freeze the ABI of
|
||||||
// Bank's serialization due to versioned nature
|
// Bank's serialization due to versioned nature
|
||||||
#[frozen_abi(digest = "FBhQnLvFHaCkXN8ZL8MaR6yQUhLgyvWqdoFeBRwsmbBo")]
|
#[frozen_abi(digest = "Fv5AFJSnZi9sssiE7Jn8bH2iTPnqu3UNc3np62r1sTsr")]
|
||||||
#[derive(Serialize, AbiExample)]
|
#[derive(Serialize, AbiExample)]
|
||||||
pub struct BankAbiTestWrapperFuture {
|
pub struct BankAbiTestWrapperFuture {
|
||||||
#[serde(serialize_with = "wrapper_future")]
|
#[serde(serialize_with = "wrapper_future")]
|
||||||
|
84
runtime/src/stake_history.rs
Normal file
84
runtime/src/stake_history.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
//! This module implements clone-on-write semantics for the SDK's `StakeHistory` to reduce
|
||||||
|
//! unnecessary cloning of the underlying vector.
|
||||||
|
use std::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The SDK's stake history with clone-on-write semantics
|
||||||
|
#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize, AbiExample)]
|
||||||
|
pub struct StakeHistory(Arc<StakeHistoryInner>);
|
||||||
|
|
||||||
|
impl Deref for StakeHistory {
|
||||||
|
type Target = StakeHistoryInner;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for StakeHistory {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
Arc::make_mut(&mut self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The inner type, which is the SDK's stake history
|
||||||
|
type StakeHistoryInner = solana_sdk::stake_history::StakeHistory;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use solana_sdk::stake_history::StakeHistoryEntry;
|
||||||
|
|
||||||
|
fn rand_stake_history_entry() -> StakeHistoryEntry {
|
||||||
|
StakeHistoryEntry {
|
||||||
|
effective: rand::random(),
|
||||||
|
activating: rand::random(),
|
||||||
|
deactivating: rand::random(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stake_history_is_cow() {
|
||||||
|
let mut stake_history = StakeHistory::default();
|
||||||
|
(100..109).for_each(|epoch| {
|
||||||
|
let entry = rand_stake_history_entry();
|
||||||
|
stake_history.add(epoch, entry);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test: Clone the stake history and **do not modify**. Assert the underlying instances
|
||||||
|
// are the same.
|
||||||
|
{
|
||||||
|
let stake_history2 = stake_history.clone();
|
||||||
|
assert_eq!(stake_history, stake_history2);
|
||||||
|
assert!(
|
||||||
|
Arc::ptr_eq(&stake_history.0, &stake_history2.0),
|
||||||
|
"Inner Arc must point to the same underlying instance"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
std::ptr::eq(stake_history.deref(), stake_history2.deref()),
|
||||||
|
"Deref must point to the same underlying instance"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test: Clone the stake history and then modify. Assert the underlying instances are
|
||||||
|
// unique.
|
||||||
|
{
|
||||||
|
let mut stake_history2 = stake_history.clone();
|
||||||
|
assert_eq!(stake_history, stake_history2);
|
||||||
|
(200..209).for_each(|epoch| {
|
||||||
|
let entry = rand_stake_history_entry();
|
||||||
|
stake_history2.add(epoch, entry);
|
||||||
|
});
|
||||||
|
assert_ne!(stake_history, stake_history2);
|
||||||
|
assert!(
|
||||||
|
!Arc::ptr_eq(&stake_history.0, &stake_history2.0),
|
||||||
|
"Inner Arc must point to a different underlying instance"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!std::ptr::eq(stake_history.deref(), stake_history2.deref()),
|
||||||
|
"Deref must point to a different underlying instance"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
stake_delegations::StakeDelegations,
|
stake_delegations::StakeDelegations,
|
||||||
|
stake_history::StakeHistory,
|
||||||
vote_account::{VoteAccount, VoteAccounts, VoteAccountsHashMap},
|
vote_account::{VoteAccount, VoteAccounts, VoteAccountsHashMap},
|
||||||
},
|
},
|
||||||
rayon::{
|
rayon::{
|
||||||
@ -17,7 +18,6 @@ use {
|
|||||||
self,
|
self,
|
||||||
state::{Delegation, StakeActivationStatus, StakeState},
|
state::{Delegation, StakeActivationStatus, StakeState},
|
||||||
},
|
},
|
||||||
stake_history::StakeHistory,
|
|
||||||
},
|
},
|
||||||
solana_stake_program::stake_state,
|
solana_stake_program::stake_state,
|
||||||
solana_vote_program::vote_state::VoteState,
|
solana_vote_program::vote_state::VoteState,
|
||||||
|
Reference in New Issue
Block a user