@@ -1719,13 +1719,18 @@ struct FlushStats {
1719
1719
num_flushed: usize,
1720
1720
num_purged: usize,
1721
1721
total_size: u64,
1722
+ store_accounts_timing: StoreAccountsTiming,
1723
+ store_accounts_total_us: u64,
1722
1724
}
1723
1725
1724
1726
impl FlushStats {
1725
1727
fn accumulate(&mut self, other: &Self) {
1726
1728
saturating_add_assign!(self.num_flushed, other.num_flushed);
1727
1729
saturating_add_assign!(self.num_purged, other.num_purged);
1728
1730
saturating_add_assign!(self.total_size, other.total_size);
1731
+ self.store_accounts_timing
1732
+ .accumulate(&other.store_accounts_timing);
1733
+ saturating_add_assign!(self.store_accounts_total_us, other.store_accounts_total_us);
1729
1734
}
1730
1735
}
1731
1736
@@ -6050,7 +6055,7 @@ impl AccountsDb {
6050
6055
// Note even if force_flush is false, we will still flush all roots <= the
6051
6056
// given `requested_flush_root`, even if some of the later roots cannot be used for
6052
6057
// cleaning due to an ongoing scan
6053
- let (total_new_cleaned_roots, num_cleaned_roots_flushed) = self
6058
+ let (total_new_cleaned_roots, num_cleaned_roots_flushed, mut flush_stats ) = self
6054
6059
.flush_rooted_accounts_cache(
6055
6060
requested_flush_root,
6056
6061
Some((&mut account_bytes_saved, &mut num_accounts_saved)),
@@ -6062,7 +6067,7 @@ impl AccountsDb {
6062
6067
// banks
6063
6068
6064
6069
// If 'should_aggressively_flush_cache', then flush the excess ones to storage
6065
- let (total_new_excess_roots, num_excess_roots_flushed) =
6070
+ let (total_new_excess_roots, num_excess_roots_flushed, flush_stats_aggressively ) =
6066
6071
if self.should_aggressively_flush_cache() {
6067
6072
// Start by flushing the roots
6068
6073
//
@@ -6071,8 +6076,9 @@ impl AccountsDb {
6071
6076
// for `should_clean`.
6072
6077
self.flush_rooted_accounts_cache(None, None)
6073
6078
} else {
6074
- (0, 0)
6079
+ (0, 0, FlushStats::default() )
6075
6080
};
6081
+ flush_stats.accumulate(&flush_stats_aggressively);
6076
6082
6077
6083
let mut excess_slot_count = 0;
6078
6084
let mut unflushable_unrooted_slot_count = 0;
@@ -6123,14 +6129,34 @@ impl AccountsDb {
6123
6129
),
6124
6130
("account_bytes_saved", account_bytes_saved, i64),
6125
6131
("num_accounts_saved", num_accounts_saved, i64),
6132
+ (
6133
+ "store_accounts_total_us",
6134
+ flush_stats.store_accounts_total_us,
6135
+ i64
6136
+ ),
6137
+ (
6138
+ "update_index_us",
6139
+ flush_stats.store_accounts_timing.update_index_elapsed,
6140
+ i64
6141
+ ),
6142
+ (
6143
+ "store_accounts_elapsed_us",
6144
+ flush_stats.store_accounts_timing.store_accounts_elapsed,
6145
+ i64
6146
+ ),
6147
+ (
6148
+ "handle_reclaims_elapsed_us",
6149
+ flush_stats.store_accounts_timing.handle_reclaims_elapsed,
6150
+ i64
6151
+ ),
6126
6152
);
6127
6153
}
6128
6154
6129
6155
fn flush_rooted_accounts_cache(
6130
6156
&self,
6131
6157
requested_flush_root: Option<Slot>,
6132
6158
should_clean: Option<(&mut usize, &mut usize)>,
6133
- ) -> (usize, usize) {
6159
+ ) -> (usize, usize, FlushStats ) {
6134
6160
let max_clean_root = should_clean.as_ref().and_then(|_| {
6135
6161
// If there is a long running scan going on, this could prevent any cleaning
6136
6162
// based on updates from slots > `max_clean_root`.
@@ -6161,12 +6187,13 @@ impl AccountsDb {
6161
6187
// Iterate from highest to lowest so that we don't need to flush earlier
6162
6188
// outdated updates in earlier roots
6163
6189
let mut num_roots_flushed = 0;
6190
+ let mut flush_stats = FlushStats::default();
6164
6191
for &root in cached_roots.iter().rev() {
6165
- if self
6166
- .flush_slot_cache_with_clean(root, should_flush_f.as_mut(), max_clean_root)
6167
- .is_some()
6192
+ if let Some(stats) =
6193
+ self.flush_slot_cache_with_clean(root, should_flush_f.as_mut(), max_clean_root)
6168
6194
{
6169
6195
num_roots_flushed += 1;
6196
+ flush_stats.accumulate(&stats);
6170
6197
}
6171
6198
6172
6199
// Regardless of whether this slot was *just* flushed from the cache by the above
@@ -6183,7 +6210,7 @@ impl AccountsDb {
6183
6210
// so that clean will actually be able to clean the slots.
6184
6211
let num_new_roots = cached_roots.len();
6185
6212
self.accounts_index.add_uncleaned_roots(cached_roots);
6186
- (num_new_roots, num_roots_flushed)
6213
+ (num_new_roots, num_roots_flushed, flush_stats )
6187
6214
}
6188
6215
6189
6216
fn do_flush_slot_cache(
@@ -6246,18 +6273,23 @@ impl AccountsDb {
6246
6273
&HashSet::default(),
6247
6274
);
6248
6275
6276
+ let mut store_accounts_timing = StoreAccountsTiming::default();
6277
+ let mut store_accounts_total_us = 0;
6249
6278
if !is_dead_slot {
6250
6279
// This ensures that all updates are written to an AppendVec, before any
6251
6280
// updates to the index happen, so anybody that sees a real entry in the index,
6252
6281
// will be able to find the account in storage
6253
6282
let flushed_store = self.create_and_insert_store(slot, total_size, "flush_slot_cache");
6254
- self.store_accounts_frozen(
6255
- (slot, &accounts[..]),
6256
- Some(hashes),
6257
- &flushed_store,
6258
- None,
6259
- StoreReclaims::Default,
6260
- );
6283
+ let (store_accounts_timing_inner, store_accounts_total_inner_us) = measure_us!(self
6284
+ .store_accounts_frozen(
6285
+ (slot, &accounts[..]),
6286
+ Some(hashes),
6287
+ &flushed_store,
6288
+ None,
6289
+ StoreReclaims::Default,
6290
+ ));
6291
+ store_accounts_timing = store_accounts_timing_inner;
6292
+ store_accounts_total_us = store_accounts_total_inner_us;
6261
6293
6262
6294
// If the above sizing function is correct, just one AppendVec is enough to hold
6263
6295
// all the data for the slot
@@ -6273,6 +6305,8 @@ impl AccountsDb {
6273
6305
num_flushed,
6274
6306
num_purged,
6275
6307
total_size,
6308
+ store_accounts_timing,
6309
+ store_accounts_total_us,
6276
6310
}
6277
6311
}
6278
6312
0 commit comments