change bg waiting metrics to percent (#20955)

* Revert part of "AcctIdx: cleanup bg threads (#20731)"

This reverts part of commit 47de4f31b6.

* change bg waiting metrics to percent
This commit is contained in:
Jeff Washington (jwash) 2021-10-26 15:09:17 -05:00 committed by GitHub
parent 4fe3354c8f
commit 4d6190a1ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 16 deletions

View File

@ -114,7 +114,7 @@ impl<T: IndexValue> AccountsIndexStorage<T> {
.and_then(|config| config.flush_threads) .and_then(|config| config.flush_threads)
.unwrap_or_else(Self::num_threads); .unwrap_or_else(Self::num_threads);
let storage = Arc::new(BucketMapHolder::new(bins, config)); let storage = Arc::new(BucketMapHolder::new(bins, config, threads));
let in_mem = (0..bins) let in_mem = (0..bins)
.into_iter() .into_iter()

View File

@ -28,6 +28,8 @@ pub struct BucketMapHolder<T: IndexValue> {
next_bucket_to_flush: Mutex<usize>, next_bucket_to_flush: Mutex<usize>,
bins: usize, bins: usize,
pub threads: usize,
// how much mb are we allowed to keep in the in-mem index? // how much mb are we allowed to keep in the in-mem index?
// Rest goes to disk. // Rest goes to disk.
pub mem_budget_mb: Option<usize>, pub mem_budget_mb: Option<usize>,
@ -130,7 +132,7 @@ impl<T: IndexValue> BucketMapHolder<T> {
} }
} }
pub fn new(bins: usize, config: &Option<AccountsIndexConfig>) -> Self { pub fn new(bins: usize, config: &Option<AccountsIndexConfig>, threads: usize) -> Self {
const DEFAULT_AGE_TO_STAY_IN_CACHE: Age = 5; const DEFAULT_AGE_TO_STAY_IN_CACHE: Age = 5;
let ages_to_stay_in_cache = config let ages_to_stay_in_cache = config
.as_ref() .as_ref()
@ -154,6 +156,7 @@ impl<T: IndexValue> BucketMapHolder<T> {
bins, bins,
startup: AtomicBool::default(), startup: AtomicBool::default(),
mem_budget_mb, mem_budget_mb,
threads,
} }
} }
@ -293,7 +296,7 @@ pub mod tests {
fn test_next_bucket_to_flush() { fn test_next_bucket_to_flush() {
solana_logger::setup(); solana_logger::setup();
let bins = 4; let bins = 4;
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default())); let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
let visited = (0..bins) let visited = (0..bins)
.into_iter() .into_iter()
.map(|_| AtomicUsize::default()) .map(|_| AtomicUsize::default())
@ -317,7 +320,7 @@ pub mod tests {
fn test_age_increment() { fn test_age_increment() {
solana_logger::setup(); solana_logger::setup();
let bins = 4; let bins = 4;
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default())); let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
for age in 0..513 { for age in 0..513 {
assert_eq!(test.current_age(), (age % 256) as Age); assert_eq!(test.current_age(), (age % 256) as Age);
@ -337,7 +340,7 @@ pub mod tests {
fn test_throttle() { fn test_throttle() {
solana_logger::setup(); solana_logger::setup();
let bins = 100; let bins = 100;
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default())); let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
let bins = test.bins as u64; let bins = test.bins as u64;
let interval_ms = test.age_interval_ms(); let interval_ms = test.age_interval_ms();
// 90% of time elapsed, all but 1 bins flushed, should not wait since we'll end up right on time // 90% of time elapsed, all but 1 bins flushed, should not wait since we'll end up right on time
@ -366,7 +369,7 @@ pub mod tests {
fn test_age_time() { fn test_age_time() {
solana_logger::setup(); solana_logger::setup();
let bins = 1; let bins = 1;
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default())); let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
let threads = 2; let threads = 2;
let time = AGE_MS * 5 / 2; let time = AGE_MS * 5 / 2;
let expected = (time / AGE_MS) as Age; let expected = (time / AGE_MS) as Age;
@ -386,7 +389,7 @@ pub mod tests {
fn test_age_broad() { fn test_age_broad() {
solana_logger::setup(); solana_logger::setup();
let bins = 4; let bins = 4;
let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default())); let test = BucketMapHolder::<u64>::new(bins, &Some(AccountsIndexConfig::default()), 1);
assert_eq!(test.current_age(), 0); assert_eq!(test.current_age(), 0);
for _ in 0..bins { for _ in 0..bins {
assert!(!test.all_buckets_flushed_at_current_age()); assert!(!test.all_buckets_flushed_at_current_age());

View File

@ -88,9 +88,8 @@ impl BucketMapHolderStats {
now.saturating_sub(last) // could saturate to 0. That is ok. now.saturating_sub(last) // could saturate to 0. That is ok.
} }
fn ms_per_age<T: IndexValue>(&self, storage: &BucketMapHolder<T>) -> u64 { fn ms_per_age<T: IndexValue>(&self, storage: &BucketMapHolder<T>, elapsed_ms: u64) -> u64 {
if !storage.get_startup() { if !storage.get_startup() {
let elapsed_ms = self.get_elapsed_ms_and_reset();
let age_now = storage.current_age(); let age_now = storage.current_age();
let last_age = self.last_age.swap(age_now, Ordering::Relaxed) as u64; let last_age = self.last_age.swap(age_now, Ordering::Relaxed) as u64;
let mut age_now = age_now as u64; let mut age_now = age_now as u64;
@ -126,12 +125,22 @@ impl BucketMapHolderStats {
} }
} }
fn calc_percent(&self, ms: u64, elapsed_ms: u64) -> f32 {
if elapsed_ms == 0 {
0.0
} else {
ms as f32 / elapsed_ms as f32
}
}
pub fn report_stats<T: IndexValue>(&self, storage: &BucketMapHolder<T>) { pub fn report_stats<T: IndexValue>(&self, storage: &BucketMapHolder<T>) {
if !self.last_time.should_update(STATS_INTERVAL_MS) { if !self.last_time.should_update(STATS_INTERVAL_MS) {
return; return;
} }
let ms_per_age = self.ms_per_age(storage); let elapsed_ms = self.get_elapsed_ms_and_reset();
let ms_per_age = self.ms_per_age(storage, elapsed_ms);
let in_mem_per_bucket_counts = self let in_mem_per_bucket_counts = self
.per_bucket_count .per_bucket_count
@ -151,11 +160,17 @@ impl BucketMapHolderStats {
let in_mem_stats = Self::get_stats(in_mem_per_bucket_counts); let in_mem_stats = Self::get_stats(in_mem_per_bucket_counts);
let disk_stats = Self::get_stats(disk_per_bucket_counts); let disk_stats = Self::get_stats(disk_per_bucket_counts);
const US_PER_MS: u64 = 1_000;
// all metrics during startup are written to a different data point // all metrics during startup are written to a different data point
let startup = storage.get_startup(); let startup = storage.get_startup();
let was_startup = self.last_was_startup.swap(startup, Ordering::Relaxed); let was_startup = self.last_was_startup.swap(startup, Ordering::Relaxed);
// sum of elapsed time in each thread
let mut thread_time_elapsed_ms = elapsed_ms * storage.threads as u64;
datapoint_info!( datapoint_info!(
if startup || was_startup { if startup || was_startup {
thread_time_elapsed_ms *= 2; // more threads are allocated during startup
"accounts_index_startup" "accounts_index_startup"
} else { } else {
"accounts_index" "accounts_index"
@ -167,14 +182,20 @@ impl BucketMapHolderStats {
), ),
("count", self.count.load(Ordering::Relaxed), i64), ("count", self.count.load(Ordering::Relaxed), i64),
( (
"bg_waiting_us", "bg_waiting_percent",
self.bg_waiting_us.swap(0, Ordering::Relaxed), self.calc_percent(
i64 self.bg_waiting_us.swap(0, Ordering::Relaxed) / US_PER_MS,
thread_time_elapsed_ms
),
f64
), ),
( (
"bg_throttling_wait_us", "bg_throttling_wait_percent",
self.bg_throttling_wait_us.swap(0, Ordering::Relaxed), self.calc_percent(
i64 self.bg_throttling_wait_us.swap(0, Ordering::Relaxed) / US_PER_MS,
thread_time_elapsed_ms
),
f64
), ),
( (
"held_in_mem_slot_list_len", "held_in_mem_slot_list_len",

View File

@ -871,6 +871,7 @@ mod tests {
let holder = Arc::new(BucketMapHolder::new( let holder = Arc::new(BucketMapHolder::new(
BINS_FOR_TESTING, BINS_FOR_TESTING,
&Some(AccountsIndexConfig::default()), &Some(AccountsIndexConfig::default()),
1,
)); ));
let bin = 0; let bin = 0;
InMemAccountsIndex::new(&holder, bin) InMemAccountsIndex::new(&holder, bin)