From 5c00b3dc6e5d5912699093e295da4e5c1a135f17 Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Sat, 1 Feb 2025 21:54:39 -0500 Subject: [PATCH 1/2] Improve in-memory IO performance, remove runtime borrow checking --- core/io/memory.rs | 63 ++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/core/io/memory.rs b/core/io/memory.rs index 6fc960e13..f95d82a75 100644 --- a/core/io/memory.rs +++ b/core/io/memory.rs @@ -3,15 +3,15 @@ use crate::Result; use log::debug; use std::{ - cell::{RefCell, RefMut}, + cell::{RefCell, UnsafeCell}, collections::BTreeMap, rc::Rc, sync::Arc, }; pub struct MemoryIO { - pages: RefCell>, - size: RefCell, + pages: UnsafeCell>, + size: UnsafeCell, } // TODO: page size flag @@ -23,23 +23,32 @@ impl MemoryIO { pub fn new() -> Result> { debug!("Using IO backend 'memory'"); Ok(Arc::new(Self { - pages: RefCell::new(BTreeMap::new()), - size: RefCell::new(0), + pages: BTreeMap::new().into(), + size: 0.into(), })) } - fn get_or_allocate_page(&self, page_no: usize) -> RefMut { - let pages = self.pages.borrow_mut(); - RefMut::map(pages, |p| { - p.entry(page_no).or_insert_with(|| Box::new([0; PAGE_SIZE])) - }) + #[allow(clippy::mut_from_ref)] + fn get_or_allocate_page(&self, page_no: usize) -> &mut MemPage { + unsafe { + let pages = &mut *self.pages.get(); + pages + .entry(page_no) + .or_insert_with(|| Box::new([0; PAGE_SIZE])) + } } - fn get_page(&self, page_no: usize) -> Option> { - match RefMut::filter_map(self.pages.borrow_mut(), |pages| pages.get_mut(&page_no)) { - Ok(page) => Some(page), - Err(_) => None, - } + fn get_page(&self, page_no: usize) -> Option<&MemPage> { + unsafe { (*self.pages.get()).get(&page_no) } + } + + #[allow(clippy::mut_from_ref)] + fn get_size_mut(&self) -> &mut usize { + unsafe { &mut *self.size.get() } + } + + fn get_size(&self) -> usize { + unsafe { *self.size.get() } } } @@ -71,7 +80,6 @@ pub struct MemoryFile { } impl File for MemoryFile { - // no-ops fn lock_file(&self, _exclusive: bool) -> Result<()> { Ok(()) } @@ -90,7 +98,7 @@ impl File for MemoryFile { return Ok(()); } - let file_size = *self.io.size.borrow(); + let file_size = self.io.get_size(); if pos >= file_size { c.complete(0); return Ok(()); @@ -108,15 +116,10 @@ impl File for MemoryFile { let page_offset = offset % PAGE_SIZE; let bytes_to_read = remaining.min(PAGE_SIZE - page_offset); if let Some(page) = self.io.get_page(page_no) { - { - let page_data = &*page; - read_buf.as_mut_slice()[buf_offset..buf_offset + bytes_to_read] - .copy_from_slice(&page_data[page_offset..page_offset + bytes_to_read]); - } + read_buf.as_mut_slice()[buf_offset..buf_offset + bytes_to_read] + .copy_from_slice(&page[page_offset..page_offset + bytes_to_read]); } else { - for b in &mut read_buf.as_mut_slice()[buf_offset..buf_offset + bytes_to_read] { - *b = 0; - } + read_buf.as_mut_slice()[buf_offset..buf_offset + bytes_to_read].fill(0); } offset += bytes_to_read; @@ -147,7 +150,7 @@ impl File for MemoryFile { let bytes_to_write = remaining.min(PAGE_SIZE - page_offset); { - let mut page = self.io.get_or_allocate_page(page_no); + let page = self.io.get_or_allocate_page(page_no); page[page_offset..page_offset + bytes_to_write] .copy_from_slice(&data[buf_offset..buf_offset + bytes_to_write]); } @@ -157,10 +160,8 @@ impl File for MemoryFile { remaining -= bytes_to_write; } - { - let mut size = self.io.size.borrow_mut(); - *size = (*size).max(pos + buf_len); - } + let size = self.io.get_size_mut(); + *size = (*size).max(pos + buf_len); c.complete(buf_len as i32); Ok(()) @@ -173,7 +174,7 @@ impl File for MemoryFile { } fn size(&self) -> Result { - Ok(*self.io.size.borrow() as u64) + Ok(self.io.get_size() as u64) } } From b5a5b34329f57a5aec74c1653e71ff1bedd270ec Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Sat, 1 Feb 2025 23:04:42 -0500 Subject: [PATCH 2/2] Use Cell for size in memoryio in place of unsafecell --- core/io/memory.rs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/core/io/memory.rs b/core/io/memory.rs index f95d82a75..18decf78a 100644 --- a/core/io/memory.rs +++ b/core/io/memory.rs @@ -3,7 +3,7 @@ use crate::Result; use log::debug; use std::{ - cell::{RefCell, UnsafeCell}, + cell::{Cell, RefCell, UnsafeCell}, collections::BTreeMap, rc::Rc, sync::Arc, @@ -11,7 +11,7 @@ use std::{ pub struct MemoryIO { pages: UnsafeCell>, - size: UnsafeCell, + size: Cell, } // TODO: page size flag @@ -41,15 +41,6 @@ impl MemoryIO { fn get_page(&self, page_no: usize) -> Option<&MemPage> { unsafe { (*self.pages.get()).get(&page_no) } } - - #[allow(clippy::mut_from_ref)] - fn get_size_mut(&self) -> &mut usize { - unsafe { &mut *self.size.get() } - } - - fn get_size(&self) -> usize { - unsafe { *self.size.get() } - } } impl IO for Arc { @@ -98,7 +89,7 @@ impl File for MemoryFile { return Ok(()); } - let file_size = self.io.get_size(); + let file_size = self.io.size.get(); if pos >= file_size { c.complete(0); return Ok(()); @@ -160,8 +151,9 @@ impl File for MemoryFile { remaining -= bytes_to_write; } - let size = self.io.get_size_mut(); - *size = (*size).max(pos + buf_len); + self.io + .size + .set(core::cmp::max(pos + buf_len, self.io.size.get())); c.complete(buf_len as i32); Ok(()) @@ -174,7 +166,7 @@ impl File for MemoryFile { } fn size(&self) -> Result { - Ok(self.io.get_size() as u64) + Ok(self.io.size.get() as u64) } }