Skip to content

Commit 2a02c67

Browse files
committed
Adding an API to calculate storage size from the stored data lengths
1 parent 6865683 commit 2a02c67

File tree

5 files changed

+62
-27
lines changed

5 files changed

+62
-27
lines changed

accounts-db/src/accounts_db.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -7829,7 +7829,8 @@ impl AccountsDb {
78297829
let mut offsets = offsets.iter().cloned().collect::<Vec<_>>();
78307830
// sort so offsets are in order. This improves efficiency of loading the accounts.
78317831
offsets.sort_unstable();
7832-
let dead_bytes = store.accounts.get_account_sizes(&offsets).iter().sum();
7832+
let data_lens = store.accounts.get_account_data_lens(offsets);
7833+
let dead_bytes = store.accounts.calculate_storage_size(&data_lens);
78337834
store.remove_accounts(dead_bytes, reset_accounts, offsets.len());
78347835
if Self::is_shrinking_productive(&store)
78357836
&& self.is_candidate_for_shrink(&store)
@@ -8502,7 +8503,7 @@ impl AccountsDb {
85028503
rent_collector: &RentCollector,
85038504
storage_info: &StorageSizeAndCountMap,
85048505
) -> SlotIndexGenerationInfo {
8505-
if storage.accounts.get_account_sizes(&[0]).is_empty() {
8506+
if storage.accounts.get_account_data_lens(&[0]).is_empty() {
85068507
return SlotIndexGenerationInfo::default();
85078508
}
85088509
let secondary = !self.account_indexes.is_empty();

accounts-db/src/accounts_file.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -325,17 +325,29 @@ impl AccountsFile {
325325
})
326326
}
327327

328-
/// for each offset in `sorted_offsets`, return the account size
329-
pub(crate) fn get_account_sizes(&self, sorted_offsets: &[usize]) -> Vec<usize> {
328+
/// for each offset in `sorted_offsets`, get the data size
329+
pub(crate) fn get_account_data_lens(&self, sorted_offsets: &[usize]) -> Vec<usize> {
330330
match self {
331-
Self::AppendVec(av) => av.get_account_sizes(sorted_offsets),
331+
Self::AppendVec(av) => av.get_account_data_lens(sorted_offsets),
332332
Self::TieredStorage(ts) => ts
333333
.reader()
334-
.and_then(|reader| reader.get_account_sizes(sorted_offsets).ok())
334+
.and_then(|reader| reader.get_account_data_lens(sorted_offsets).ok())
335335
.unwrap_or_default(),
336336
}
337337
}
338338

339+
/// Calculate the amount of storage required for the passed in data lengths
340+
/// Only need data lengths, as the number of accounts can be inferred from
341+
/// length of the vector, and the account size is static
342+
pub(crate) fn calculate_storage_size(&self, data_lens: &[usize]) -> usize {
343+
match self {
344+
Self::AppendVec(av) => av.calculate_storage_size(data_lens),
345+
Self::TieredStorage(ts) => ts
346+
.reader()
347+
.map_or(0, |reader| reader.calculate_storage_size(data_lens)),
348+
}
349+
}
350+
339351
/// iterate over all entries to put in index
340352
pub(crate) fn scan_index(&self, callback: impl FnMut(IndexInfo)) {
341353
match self {

accounts-db/src/append_vec.rs

+21-15
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,6 @@ impl IsZeroLamport for IndexInfo {
165165
struct AccountOffsets {
166166
/// offset to the end of the &[u8] data
167167
offset_to_end_of_data: usize,
168-
/// # of bytes (aligned) to store this account, including variable sized data
169-
stored_size_aligned: usize,
170168
}
171169

172170
#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
@@ -889,14 +887,15 @@ impl AppendVec {
889887
&self,
890888
offset: usize,
891889
) -> Option<(StoredMeta, solana_account::AccountSharedData)> {
892-
let sizes = self.get_account_sizes(&[offset]);
890+
let data_len = self.get_account_data_lens(&[offset]);
891+
let sizes = self.calculate_storage_size(&data_len);
893892
let result = self.get_stored_account_meta_callback(offset, |r_callback| {
894893
let r2 = self.get_account_shared_data(offset);
895894
assert!(solana_account::accounts_equal(
896895
&r_callback,
897896
r2.as_ref().unwrap()
898897
));
899-
assert_eq!(sizes, vec![r_callback.stored_size()]);
898+
assert_eq!(sizes, r_callback.stored_size());
900899
let meta = r_callback.meta().clone();
901900
Some((meta, r_callback.to_account_shared_data()))
902901
});
@@ -906,7 +905,7 @@ impl AppendVec {
906905
.is_none());
907906
assert!(self.get_account_shared_data(offset).is_none());
908907
// it has different rules for checking len and returning None
909-
assert!(sizes.is_empty());
908+
assert!(sizes == 0);
910909
}
911910
result.flatten()
912911
}
@@ -926,12 +925,10 @@ impl AppendVec {
926925
let stored_size_unaligned = STORE_META_OVERHEAD
927926
.checked_add(stored_meta.data_len as usize)
928927
.expect("stored size cannot overflow");
929-
let stored_size_aligned = u64_align!(stored_size_unaligned);
930928
let offset_to_end_of_data = start_offset + stored_size_unaligned;
931929

932930
AccountOffsets {
933931
offset_to_end_of_data,
934-
stored_size_aligned,
935932
}
936933
}
937934

@@ -1098,8 +1095,13 @@ impl AppendVec {
10981095
}
10991096
}
11001097

1101-
/// for each offset in `sorted_offsets`, get the size of the account. No other information is needed for the account.
1102-
pub(crate) fn get_account_sizes(&self, sorted_offsets: &[usize]) -> Vec<usize> {
1098+
/// Calculate the amount of storage required for the passed in data lengths
1099+
pub(crate) fn calculate_storage_size(&self, data_len: &[usize]) -> usize {
1100+
data_len.iter().map(|len| aligned_stored_size(*len)).sum()
1101+
}
1102+
1103+
/// for each offset in `sorted_offsets`, get the the amount of data stored in the account.
1104+
pub(crate) fn get_account_data_lens(&self, sorted_offsets: &[usize]) -> Vec<usize> {
11031105
// self.len() is an atomic load, so only do it once
11041106
let self_len = self.len();
11051107
let mut account_sizes = Vec::with_capacity(sorted_offsets.len());
@@ -1115,7 +1117,7 @@ impl AppendVec {
11151117
// data doesn't fit, so don't include
11161118
break;
11171119
}
1118-
account_sizes.push(next.stored_size_aligned);
1120+
account_sizes.push(stored_meta.data_len as usize);
11191121
}
11201122
}
11211123
AppendVecFileBacking::File(file) => {
@@ -1143,7 +1145,7 @@ impl AppendVec {
11431145
// data doesn't fit, so don't include
11441146
break;
11451147
}
1146-
account_sizes.push(next.stored_size_aligned);
1148+
account_sizes.push(stored_meta.data_len as usize);
11471149
}
11481150
}
11491151
}
@@ -1699,7 +1701,7 @@ pub mod tests {
16991701
let size = 1000;
17001702
let mut indexes = vec![];
17011703
let now = Instant::now();
1702-
let mut sizes = vec![];
1704+
let mut sizes: Vec<usize> = vec![];
17031705
for sample in 0..size {
17041706
// sample + 1 is so sample = 0 won't be used.
17051707
// sample = 0 produces default account with default pubkey
@@ -1708,7 +1710,10 @@ pub mod tests {
17081710
let pos = av.append_account_test(&account).unwrap();
17091711
assert_eq!(av.get_account_test(pos).unwrap(), account);
17101712
indexes.push(pos);
1711-
assert_eq!(sizes, av.get_account_sizes(&indexes));
1713+
assert_eq!(
1714+
sizes.iter().sum::<usize>(),
1715+
av.calculate_storage_size(&av.get_account_data_lens(indexes.as_slice()))
1716+
);
17121717
}
17131718
trace!("append time: {} ms", now.elapsed().as_millis());
17141719

@@ -2071,8 +2076,9 @@ pub mod tests {
20712076
let (append_vec, _) =
20722077
AppendVec::new_from_file(&temp_file.path, total_stored_size, storage_access).unwrap();
20732078

2074-
let account_sizes = append_vec.get_account_sizes(account_offsets.as_slice());
2075-
assert_eq!(account_sizes, stored_sizes);
2079+
let account_sizes = append_vec
2080+
.calculate_storage_size(&append_vec.get_account_data_lens(account_offsets.as_slice()));
2081+
assert_eq!(account_sizes, total_stored_size);
20762082
}
20772083

20782084
/// A helper function for testing different scenario for scan_*.

accounts-db/src/tiered_storage/hot.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -613,8 +613,15 @@ impl HotStorageReader {
613613
Ok(())
614614
}
615615

616-
/// for each offset in `sorted_offsets`, return the account size
617-
pub(crate) fn get_account_sizes(
616+
/// Calculate the amount of storage required for the passed in data lengths
617+
/// Only need data lengths, as the number of accounts can be inferred from
618+
/// length of the vector, and the account size is static
619+
pub(crate) fn calculate_storage_size(&self, data_len: &[usize]) -> usize {
620+
data_len.iter().map(|data_len| stored_size(*data_len)).sum()
621+
}
622+
623+
/// for each offset in `sorted_offsets`, return the length of data stored in the account
624+
pub(crate) fn get_account_data_lens(
618625
&self,
619626
sorted_offsets: &[usize],
620627
) -> TieredStorageResult<Vec<usize>> {
@@ -625,7 +632,7 @@ impl HotStorageReader {
625632
let meta = self.get_account_meta_from_offset(account_offset)?;
626633
let account_block = self.get_account_block(account_offset, index_offset)?;
627634
let data_len = meta.account_data_size(account_block);
628-
result.push(stored_size(data_len));
635+
result.push(data_len);
629636
}
630637
Ok(result)
631638
}

accounts-db/src/tiered_storage/readable.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,22 @@ impl TieredStorageReader {
171171
}
172172
}
173173

174-
/// for each offset in `sorted_offsets`, return the account size
175-
pub(crate) fn get_account_sizes(
174+
/// Calculate the amount of storage required for the passed in data lengths
175+
/// Only need data lengths, as the number of accounts can be inferred from
176+
/// length of the vector, and the account size is static
177+
pub(crate) fn calculate_storage_size(&self, data_len: &[usize]) -> usize {
178+
match self {
179+
Self::Hot(hot) => hot.calculate_storage_size(data_len),
180+
}
181+
}
182+
183+
/// for each offset in `sorted_offsets`, return the length of data stored in the account
184+
pub(crate) fn get_account_data_lens(
176185
&self,
177186
sorted_offsets: &[usize],
178187
) -> TieredStorageResult<Vec<usize>> {
179188
match self {
180-
Self::Hot(hot) => hot.get_account_sizes(sorted_offsets),
189+
Self::Hot(hot) => hot.get_account_data_lens(sorted_offsets),
181190
}
182191
}
183192

0 commit comments

Comments
 (0)