From 66e40e9a7a712c442a29a5f14228f6fc7ef0acdc Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sat, 4 May 2024 11:00:05 +0200 Subject: [PATCH] Avoid per-access overhead in WritablePage using unsafe code. --- src/tree_store/page_store/cached_file.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/tree_store/page_store/cached_file.rs b/src/tree_store/page_store/cached_file.rs index 747609ba..23708653 100644 --- a/src/tree_store/page_store/cached_file.rs +++ b/src/tree_store/page_store/cached_file.rs @@ -3,6 +3,7 @@ use crate::tree_store::LEAF; use crate::{DatabaseError, Result, StorageBackend, StorageError}; use std::collections::BTreeMap; use std::io; +use std::mem::ManuallyDrop; use std::ops::{Index, IndexMut}; use std::slice::SliceIndex; #[cfg(feature = "cache_metrics")] @@ -30,23 +31,27 @@ impl CachePriority { pub(super) struct WritablePage { buffer: Arc>, offset: u64, - data: Option>, + data: ManuallyDrop>, priority: CachePriority, } impl WritablePage { pub(super) fn mem(&self) -> &[u8] { - self.data.as_ref().unwrap() + &self.data } pub(super) fn mem_mut(&mut self) -> &mut [u8] { - Arc::get_mut(self.data.as_mut().unwrap()).unwrap() + let data = Arc::get_mut(&mut self.data); + debug_assert!(data.is_some()); + // SAFETY: `self` has the sole reference to `data`. + unsafe { data.unwrap_unchecked() } } } impl Drop for WritablePage { fn drop(&mut self) { - let data = self.data.take().unwrap(); + // SAFETY: `drop` is called at most once + let data = unsafe { ManuallyDrop::take(&mut self.data) }; self.buffer .lock() .unwrap() @@ -487,7 +492,7 @@ impl PagedCachedFile { Ok(WritablePage { buffer: self.write_buffer.clone(), offset, - data: Some(data), + data: ManuallyDrop::new(data), priority, }) }