Skip to content

Commit

Permalink
accounts-db: Sampled LRU eviction
Browse files Browse the repository at this point in the history
Instead of rigid LRU eviction, perform sampled LRU eviction.

Sampled LRU eviction takes K random keys and picks the one with the
lowest update timestamp. This way, even though the evicted element is
not always the oldest in the whole cache, removes the necessity of
maintaining a queue and reduces the contention caused by locking the
queue.

The K parameter is configurable, but the best performing value so far
was 16 and it's used as the default one.

The new eviction mechanism results in performance improvement in the
cache eviction benchmarks:

```
read_only_accounts_cache_eviction_lo_hi/store/8
                        time:   [17.986 µs 18.277 µs 18.566 µs]
                        change: [-42.722% -35.752% -28.175%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  1 (1.00%) low mild
  2 (2.00%) high mild
  2 (2.00%) high severe
read_only_accounts_cache_eviction_lo_hi/store/16
                        time:   [19.124 µs 19.269 µs 19.400 µs]
                        change: [-50.486% -45.520% -41.321%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  2 (2.00%) high mild
  3 (3.00%) high severe
read_only_accounts_cache_eviction_lo_hi/store/32
                        time:   [20.350 µs 21.194 µs 22.227 µs]
                        change: [-63.890% -60.900% -57.730%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 12 outliers among 100 measurements (12.00%)
  1 (1.00%) high mild
  11 (11.00%) high severe
read_only_accounts_cache_eviction_lo_hi/store/64
                        time:   [28.981 µs 30.921 µs 32.968 µs]
                        change: [-68.963% -65.463% -61.849%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 6 outliers among 100 measurements (6.00%)
  1 (1.00%) low mild
  3 (3.00%) high mild
  2 (2.00%) high severe
```
  • Loading branch information
vadorovsky committed Jan 2, 2025
1 parent c709163 commit 142cc80
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 100 deletions.
2 changes: 2 additions & 0 deletions accounts-db/benches/read_only_accounts_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fn bench_read_only_accounts_cache(c: &mut Criterion) {
let cache = Arc::new(ReadOnlyAccountsCache::new(
AccountsDb::DEFAULT_MAX_READ_ONLY_CACHE_DATA_SIZE_LO,
AccountsDb::DEFAULT_MAX_READ_ONLY_CACHE_DATA_SIZE_HI,
AccountsDb::DEFAULT_READ_ONLY_CACHE_EVICT_SAMPLE_SIZE,
AccountsDb::READ_ONLY_CACHE_MS_TO_SKIP_LRU_UPDATE,
));

Expand Down Expand Up @@ -181,6 +182,7 @@ fn bench_read_only_accounts_cache_eviction(
let cache = Arc::new(ReadOnlyAccountsCache::new(
max_data_size_lo,
max_data_size_hi,
AccountsDb::DEFAULT_READ_ONLY_CACHE_EVICT_SAMPLE_SIZE,
AccountsDb::READ_ONLY_CACHE_MS_TO_SKIP_LRU_UPDATE,
));

Expand Down
10 changes: 10 additions & 0 deletions accounts-db/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ pub const ACCOUNTS_DB_CONFIG_FOR_TESTING: AccountsDbConfig = AccountsDbConfig {
shrink_paths: None,
shrink_ratio: DEFAULT_ACCOUNTS_SHRINK_THRESHOLD_OPTION,
read_cache_limit_bytes: None,
read_cache_evict_sample_size: None,
write_cache_limit_bytes: None,
ancient_append_vec_offset: None,
ancient_storage_ideal_size: None,
Expand All @@ -525,6 +526,7 @@ pub const ACCOUNTS_DB_CONFIG_FOR_BENCHMARKS: AccountsDbConfig = AccountsDbConfig
shrink_paths: None,
shrink_ratio: DEFAULT_ACCOUNTS_SHRINK_THRESHOLD_OPTION,
read_cache_limit_bytes: None,
read_cache_evict_sample_size: None,
write_cache_limit_bytes: None,
ancient_append_vec_offset: None,
ancient_storage_ideal_size: None,
Expand Down Expand Up @@ -649,6 +651,7 @@ pub struct AccountsDbConfig {
/// The low and high watermark sizes for the read cache, in bytes.
/// If None, defaults will be used.
pub read_cache_limit_bytes: Option<(usize, usize)>,
pub read_cache_evict_sample_size: Option<usize>,
pub write_cache_limit_bytes: Option<u64>,
/// if None, ancient append vecs are set to ANCIENT_APPEND_VEC_DEFAULT_OFFSET
/// Some(offset) means include slots up to (max_slot - (slots_per_epoch - 'offset'))
Expand Down Expand Up @@ -1891,6 +1894,9 @@ impl AccountsDb {
#[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
const DEFAULT_MAX_READ_ONLY_CACHE_DATA_SIZE_HI: usize = 410 * 1024 * 1024;

#[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
const DEFAULT_READ_ONLY_CACHE_EVICT_SAMPLE_SIZE: usize = 8;

pub fn default_for_tests() -> Self {
Self::new_single_for_tests()
}
Expand Down Expand Up @@ -1972,6 +1978,9 @@ impl AccountsDb {
Self::DEFAULT_MAX_READ_ONLY_CACHE_DATA_SIZE_LO,
Self::DEFAULT_MAX_READ_ONLY_CACHE_DATA_SIZE_HI,
));
let read_cache_evict_sample_size = accounts_db_config
.read_cache_evict_sample_size
.unwrap_or(Self::DEFAULT_READ_ONLY_CACHE_EVICT_SAMPLE_SIZE);

// Increase the stack for foreground threads
// rayon needs a lot of stack
Expand Down Expand Up @@ -2027,6 +2036,7 @@ impl AccountsDb {
read_only_accounts_cache: ReadOnlyAccountsCache::new(
read_cache_size.0,
read_cache_size.1,
read_cache_evict_sample_size,
Self::READ_ONLY_CACHE_MS_TO_SKIP_LRU_UPDATE,
),
write_cache_limit_bytes: accounts_db_config.write_cache_limit_bytes,
Expand Down
Loading

0 comments on commit 142cc80

Please sign in to comment.