From 46e5350d8c25c6e61f4842ff6bb20b0690f1fa41 Mon Sep 17 00:00:00 2001 From: "Jeff Washington (jwash)" Date: Wed, 15 Dec 2021 15:41:11 -0600 Subject: [PATCH] AcctInfo: store offset in AccountInfo as u32 (#21895) --- runtime/src/account_info.rs | 50 +++++++++++++++++++++++++++++++------ runtime/src/accounts_db.rs | 6 ++--- runtime/src/append_vec.rs | 4 +-- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/runtime/src/account_info.rs b/runtime/src/account_info.rs index 675ff195e4..e05f68865b 100644 --- a/runtime/src/account_info.rs +++ b/runtime/src/account_info.rs @@ -5,6 +5,7 @@ use crate::{ accounts_db::{AppendVecId, CACHE_VIRTUAL_OFFSET}, accounts_index::{IsCached, ZeroLamport}, + append_vec::ALIGN_BOUNDARY_OFFSET, }; /// offset within an append vec to account data @@ -54,13 +55,19 @@ impl StorageLocation { } } +/// how large the offset we store in AccountInfo is +/// Note this is a smaller datatype than 'Offset' +/// AppendVecs store accounts aligned to u64, so offset is always a multiple of 8 (sizeof(u64)) +pub type OffsetReduced = u32; + #[derive(Default, Debug, PartialEq, Clone, Copy)] pub struct AccountInfo { /// index identifying the append storage store_id: AppendVecId, - /// offset into the storage - offset: Offset, + /// offset = 'reduced_offset' / ALIGN_BOUNDARY_OFFSET into the storage + /// Note this is a smaller type than 'Offset' + reduced_offset: OffsetReduced, /// needed to track shrink candidacy in bytes. Used to update the number /// of alive bytes in an AppendVec as newer slots purge outdated entries @@ -99,7 +106,7 @@ impl AccountInfo { pub fn new(storage_location: StorageLocation, stored_size: StoredSize, lamports: u64) -> Self { assert_eq!(stored_size & ALL_FLAGS, 0); let mut stored_size_mask = stored_size; - let (store_id, offset) = match storage_location { + let (store_id, raw_offset) = match storage_location { StorageLocation::AppendVec(store_id, offset) => (store_id, offset), StorageLocation::Cached => { stored_size_mask |= IS_CACHED_STORE_ID_FLAG; @@ -111,11 +118,14 @@ impl AccountInfo { if lamports == 0 { stored_size_mask |= IS_ZERO_LAMPORT_FLAG; } - Self { + let reduced_offset: OffsetReduced = (raw_offset / ALIGN_BOUNDARY_OFFSET) as OffsetReduced; + let result = Self { store_id, - offset, + reduced_offset, stored_size_mask, - } + }; + assert_eq!(result.offset(), raw_offset, "illegal offset"); + result } pub fn store_id(&self) -> AppendVecId { @@ -124,7 +134,7 @@ impl AccountInfo { } pub fn offset(&self) -> Offset { - self.offset + (self.reduced_offset as Offset) * ALIGN_BOUNDARY_OFFSET } pub fn stored_size(&self) -> StoredSize { @@ -136,7 +146,31 @@ impl AccountInfo { if self.is_cached() { StorageLocation::Cached } else { - StorageLocation::AppendVec(self.store_id, self.offset) + StorageLocation::AppendVec(self.store_id, self.offset()) } } } +#[cfg(test)] +mod test { + use {super::*, crate::append_vec::MAXIMUM_APPEND_VEC_FILE_SIZE}; + + #[test] + fn test_limits() { + for offset in [ + MAXIMUM_APPEND_VEC_FILE_SIZE as Offset, + 0, + ALIGN_BOUNDARY_OFFSET, + 4 * ALIGN_BOUNDARY_OFFSET, + ] { + let info = AccountInfo::new(StorageLocation::AppendVec(0, offset), 0, 0); + assert!(info.offset() == offset); + } + } + + #[test] + #[should_panic(expected = "illegal offset")] + fn test_alignment() { + let offset = 1; // not aligned + AccountInfo::new(StorageLocation::AppendVec(0, offset), 0, 0); + } +} diff --git a/runtime/src/accounts_db.rs b/runtime/src/accounts_db.rs index 97b0cd0ef2..49acb5f18c 100644 --- a/runtime/src/accounts_db.rs +++ b/runtime/src/accounts_db.rs @@ -22,7 +22,7 @@ use std::{thread::sleep, time::Duration}; use { crate::{ - account_info::{AccountInfo, StorageLocation, StoredSize}, + account_info::{AccountInfo, Offset, StorageLocation, StoredSize}, accounts_background_service::{DroppedSlotsSender, SendDroppedBankCallback}, accounts_cache::{AccountsCache, CachedAccount, SlotCache}, accounts_hash::{AccountsHash, CalculateHashIntermediate, HashStats, PreviousPass}, @@ -120,7 +120,7 @@ const CACHE_VIRTUAL_WRITE_VERSION: StoredMetaWriteVersion = 0; // for entries in the cache, so that operations that take a storage entry can maintain // a common interface when interacting with cached accounts. This version is "virtual" in // that it doesn't actually map to an entry in an AppendVec. -pub(crate) const CACHE_VIRTUAL_OFFSET: usize = 0; +pub(crate) const CACHE_VIRTUAL_OFFSET: Offset = 0; const CACHE_VIRTUAL_STORED_SIZE: StoredSize = 0; pub const ACCOUNTS_DB_CONFIG_FOR_TESTING: AccountsDbConfig = AccountsDbConfig { @@ -13306,7 +13306,7 @@ pub mod tests { } let do_test = |test_params: TestParameters| { - let account_info = AccountInfo::new(StorageLocation::AppendVec(42, 123), 234, 0); + let account_info = AccountInfo::new(StorageLocation::AppendVec(42, 128), 234, 0); let pubkey = solana_sdk::pubkey::new_rand(); let mut key_set = HashSet::default(); key_set.insert(pubkey); diff --git a/runtime/src/append_vec.rs b/runtime/src/append_vec.rs index 29f13ee270..0196816372 100644 --- a/runtime/src/append_vec.rs +++ b/runtime/src/append_vec.rs @@ -30,14 +30,14 @@ use { // Data placement should be aligned at the next boundary. Without alignment accessing the memory may // crash on some architectures. -const ALIGN_BOUNDARY_OFFSET: usize = mem::size_of::(); +pub const ALIGN_BOUNDARY_OFFSET: usize = mem::size_of::(); macro_rules! u64_align { ($addr: expr) => { ($addr + (ALIGN_BOUNDARY_OFFSET - 1)) & !(ALIGN_BOUNDARY_OFFSET - 1) }; } -const MAXIMUM_APPEND_VEC_FILE_SIZE: u64 = 16 * 1024 * 1024 * 1024; // 16 GiB +pub const MAXIMUM_APPEND_VEC_FILE_SIZE: u64 = 16 * 1024 * 1024 * 1024; // 16 GiB pub type StoredMetaWriteVersion = u64;