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/store/8
                        time:   [1.9489 µs 1.9875 µs 2.0213 µs]
                        change: [-74.816% -73.964% -73.105%] (p = 0.00 < 0.05)
                        Performance has improved.
read_only_accounts_cache/store/16
                        time:   [2.0819 µs 2.1293 µs 2.1794 µs]
                        change: [-86.636% -86.144% -85.625%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) high mild
  1 (1.00%) high severe
read_only_accounts_cache/store/32
                        time:   [3.9828 µs 4.2358 µs 4.4943 µs]
                        change: [-88.027% -87.208% -86.398%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
read_only_accounts_cache/store/64
                        time:   [13.119 µs 14.813 µs 16.806 µs]
                        change: [-81.391% -78.786% -75.877%] (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

Benchmarking read_only_accounts_cache_eviction_lo_hi/store/8: Collecting 100 samples in estimated 5.0133 s (268k itera
                        time:   [19.773 µs 19.966 µs 20.156 µs]
                        change: [-34.871% -28.189% -22.243%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  2 (2.00%) high mild
  2 (2.00%) high severe
Benchmarking read_only_accounts_cache_eviction_lo_hi/store/16: Collecting 100 samples in estimated 5.0209 s (247k iter
                        time:   [20.194 µs 20.499 µs 20.805 µs]
                        change: [-43.619% -40.284% -36.721%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
Benchmarking read_only_accounts_cache_eviction_lo_hi/store/32: Collecting 100 samples in estimated 5.0245 s (207k iter
                        time:   [25.149 µs 25.889 µs 26.735 µs]
                        change: [-57.519% -53.108% -49.152%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
Benchmarking read_only_accounts_cache_eviction_lo_hi/store/64: Collecting 100 samples in estimated 5.1367 s (101k iter
                        time:   [42.863 µs 46.570 µs 50.567 µs]
                        change: [-53.591% -45.954% -36.141%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  3 (3.00%) high mild
  2 (2.00%) high severe

Benchmarking read_only_accounts_cache_eviction_hi/store/8: Collecting 100 samples in estimated 5.0776 s (268k iteratio
                        time:   [19.697 µs 19.868 µs 20.026 µs]
                        change: [-30.199% -26.774% -22.973%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  3 (3.00%) high mild
  2 (2.00%) high severe
Benchmarking read_only_accounts_cache_eviction_hi/store/16: Collecting 100 samples in estimated 5.0691 s (252k iteratiread_only_accounts_cache_eviction_hi/store/16
                        time:   [20.536 µs 20.999 µs 21.486 µs]
                        change: [-41.945% -36.618% -30.330%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  1 (1.00%) low mild
  2 (2.00%) high mild
  4 (4.00%) high severe
Benchmarking read_only_accounts_cache_eviction_hi/store/32: Collecting 100 samples in estimated 5.1200 s (212k iteratiread_only_accounts_cache_eviction_hi/store/32
                        time:   [22.710 µs 23.733 µs 24.866 µs]
                        change: [-60.256% -57.228% -54.265%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  6 (6.00%) high mild
  1 (1.00%) high severe
Benchmarking read_only_accounts_cache_eviction_hi/store/64: Collecting 100 samples in estimated 5.0774 s (91k iteratioread_only_accounts_cache_eviction_hi/store/64
                        time:   [44.758 µs 48.348 µs 52.139 µs]
                        change: [-53.228% -47.455% -41.602%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  5 (5.00%) high mild
```
  • Loading branch information
vadorovsky committed Dec 30, 2024
1 parent c709163 commit 1e0e998
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 137 deletions.
4 changes: 2 additions & 2 deletions accounts-db/benches/read_only_accounts_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +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::READ_ONLY_CACHE_MS_TO_SKIP_LRU_UPDATE,
AccountsDb::DEFAULT_READ_ONLY_CACHE_EVICT_SAMPLE_SIZE,
));

for (pubkey, account) in accounts.iter() {
Expand Down Expand Up @@ -181,7 +181,7 @@ fn bench_read_only_accounts_cache_eviction(
let cache = Arc::new(ReadOnlyAccountsCache::new(
max_data_size_lo,
max_data_size_hi,
AccountsDb::READ_ONLY_CACHE_MS_TO_SKIP_LRU_UPDATE,
AccountsDb::DEFAULT_READ_ONLY_CACHE_EVICT_SAMPLE_SIZE,
));

// Fill up the cache.
Expand Down
15 changes: 10 additions & 5 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 @@ -1880,17 +1883,16 @@ pub struct PubkeyHashAccount {
impl AccountsDb {
pub const DEFAULT_ACCOUNTS_HASH_CACHE_DIR: &'static str = "accounts_hash_cache";

// read only cache does not update lru on read of an entry unless it has been at least this many ms since the last lru update
#[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
const READ_ONLY_CACHE_MS_TO_SKIP_LRU_UPDATE: u32 = 100;

// The default high and low watermark sizes for the accounts read cache.
// If the cache size exceeds MAX_SIZE_HI, it'll evict entries until the size is <= MAX_SIZE_LO.
#[cfg_attr(feature = "dev-context-only-utils", qualifiers(pub))]
const DEFAULT_MAX_READ_ONLY_CACHE_DATA_SIZE_LO: usize = 400 * 1024 * 1024;
#[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 = 16;

pub fn default_for_tests() -> Self {
Self::new_single_for_tests()
}
Expand Down Expand Up @@ -1972,6 +1974,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,7 +2032,7 @@ impl AccountsDb {
read_only_accounts_cache: ReadOnlyAccountsCache::new(
read_cache_size.0,
read_cache_size.1,
Self::READ_ONLY_CACHE_MS_TO_SKIP_LRU_UPDATE,
read_cache_evict_sample_size,
),
write_cache_limit_bytes: accounts_db_config.write_cache_limit_bytes,
partitioned_epoch_rewards_config,
Expand Down
Loading

0 comments on commit 1e0e998

Please sign in to comment.