From cbd85678bef8cc42edf3c13cfc1be1eb41b6842a Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Mon, 28 Aug 2023 19:45:31 +0200 Subject: [PATCH] page cache: don't proactively evict EphemeralFile pages Before this patch, when dropping an EphemeralFile, we'd scan the entire `slots` to proactively evict its pages (`drop_buffers_for_immutable`). This was _necessary_ before #4994 because the page cache was a write-back cache: we'd be deleting the EphemeralFile from disk after, so, if we hadn't evicted its pages before that, write-back in `find_victim` wouldhave failed. But, since #4994, the page cache is a read-only cache, so, it's safe to keep read-only data cached. It's never going to get accessed again and eventually, `find_victim` will evict it. The only remaining advantage of `drop_buffers_for_immutable` over relying on `find_victim` is that `find_victim` has to do the clock page replacement iterations until the count reaches 0, whereas `drop_buffers_for_immutable` can kick the page out right away. However, weigh that against the cost of `drop_buffers_for_immutable`, which currently scans the entire `slots` array to find the EphemeralFile's pages. Alternatives have been proposed in #5122 and #5128, but, they come with their own overheads & trade-offs. So, let's just stop doing `drop_buffers_for_immutable` and observe the performance impact in benchmarks. --- pageserver/src/page_cache.rs | 21 --------------------- pageserver/src/tenant/ephemeral_file.rs | 5 ++--- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/pageserver/src/page_cache.rs b/pageserver/src/page_cache.rs index e1e696ddad54..833b53894f56 100644 --- a/pageserver/src/page_cache.rs +++ b/pageserver/src/page_cache.rs @@ -425,27 +425,6 @@ impl PageCache { self.lock_for_read(&mut cache_key) } - /// Immediately drop all buffers belonging to given file - pub fn drop_buffers_for_immutable(&self, drop_file_id: FileId) { - for slot_idx in 0..self.slots.len() { - let slot = &self.slots[slot_idx]; - - let mut inner = slot.inner.write().unwrap(); - if let Some(key) = &inner.key { - match key { - CacheKey::ImmutableFilePage { file_id, blkno: _ } - if *file_id == drop_file_id => - { - // remove mapping for old buffer - self.remove_mapping(key); - inner.key = None; - } - _ => {} - } - } - } - } - // // Section 2: Internal interface functions for lookup/update. // diff --git a/pageserver/src/tenant/ephemeral_file.rs b/pageserver/src/tenant/ephemeral_file.rs index b149bc978809..ce8fd9ca3e66 100644 --- a/pageserver/src/tenant/ephemeral_file.rs +++ b/pageserver/src/tenant/ephemeral_file.rs @@ -221,9 +221,8 @@ pub fn is_ephemeral_file(filename: &str) -> bool { impl Drop for EphemeralFile { fn drop(&mut self) { - // drop all pages from page cache - let cache = page_cache::get(); - cache.drop_buffers_for_immutable(self.page_cache_file_id); + // There might still be pages in the [`crate::page_cache`] for this file. + // We leave them there, [`crate::page_cache::PageCache::find_victim`] will evict them when needed. // unlink the file let res = std::fs::remove_file(&self.file.path);