From 63798c49cd783553afb1cfab15e96e96161363e6 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Thu, 21 Dec 2023 12:58:43 +1100 Subject: [PATCH] Implement read cache for Val --- storage/src/lib.rs | 2 ++ storage/src/memory_backend.rs | 15 +++++++++++++-- storage/src/read_cache.rs | 3 +++ storage/src/sled_backend.rs | 17 +++++++++++++++-- storage/src/storage_auto_ptr.rs | 2 +- storage/src/storage_backend.rs | 6 ++++-- valuescript_vm/src/vs_storage_ptr.rs | 23 +++++++++++++++++++++-- 7 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 storage/src/read_cache.rs diff --git a/storage/src/lib.rs b/storage/src/lib.rs index b0da2c2..ca6ee4b 100644 --- a/storage/src/lib.rs +++ b/storage/src/lib.rs @@ -6,6 +6,7 @@ mod demo_val; mod errors; mod rc_key; +mod read_cache; mod sled_backend; mod storage_auto_ptr; mod storage_backend; @@ -21,6 +22,7 @@ pub use self::storage_io::{StorageReader, StorageTxMut}; pub use errors::GenericError; pub use memory_backend::MemoryBackend; pub use rc_key::RcKey; +pub use read_cache::ReadCache; pub use sled_backend::SledBackend; pub use storage_auto_ptr::StorageAutoPtr; pub use storage_entity::StorageEntity; diff --git a/storage/src/memory_backend.rs b/storage/src/memory_backend.rs index fd648fc..b9c949d 100644 --- a/storage/src/memory_backend.rs +++ b/storage/src/memory_backend.rs @@ -1,21 +1,28 @@ -use std::{cell::RefCell, collections::HashMap, error::Error, rc::Weak}; +use std::{ + cell::{RefCell, RefMut}, + collections::HashMap, + error::Error, + rc::Weak, +}; use crate::{ rc_key::RcKey, storage_io::{StorageReader, StorageTxMut}, storage_ptr::StorageEntryPtr, - GenericError, StorageBackend, StoragePtr, + GenericError, ReadCache, StorageBackend, StoragePtr, }; #[derive(Default)] pub struct MemoryBackend { data: HashMap<(u64, u64, u64), Vec>, + read_cache: RefCell, } impl MemoryBackend { pub fn new() -> Self { Self { data: HashMap::new(), + read_cache: Default::default(), } } } @@ -67,6 +74,10 @@ impl StorageBackend for MemoryBackend { self.data.is_empty() } + fn get_read_cache(&self) -> RefMut { + self.read_cache.borrow_mut() + } + #[cfg(test)] fn len(&self) -> usize { self.data.len() diff --git a/storage/src/read_cache.rs b/storage/src/read_cache.rs new file mode 100644 index 0000000..b124c7a --- /dev/null +++ b/storage/src/read_cache.rs @@ -0,0 +1,3 @@ +use std::{any::Any, collections::HashMap}; + +pub type ReadCache = HashMap<(u64, u64, u64), Box>; diff --git a/storage/src/sled_backend.rs b/storage/src/sled_backend.rs index 8f04d1e..0eb509d 100644 --- a/storage/src/sled_backend.rs +++ b/storage/src/sled_backend.rs @@ -1,4 +1,10 @@ -use std::{cell::RefCell, collections::HashMap, error::Error, fmt::Display, rc::Weak}; +use std::{ + cell::{RefCell, RefMut}, + collections::HashMap, + error::Error, + fmt::Display, + rc::Weak, +}; use sled::transaction::{ ConflictableTransactionError, TransactionError, UnabortableTransactionError, @@ -8,11 +14,12 @@ use crate::{ rc_key::RcKey, storage_io::{StorageReader, StorageTxMut}, storage_ptr::StorageEntryPtr, - GenericError, StorageBackend, StoragePtr, + GenericError, ReadCache, StorageBackend, StoragePtr, }; pub struct SledBackend { db: sled::Db, + read_cache: RefCell, } impl SledBackend { @@ -22,12 +29,14 @@ impl SledBackend { { Ok(Self { db: sled::open(path)?, + read_cache: Default::default(), }) } pub fn open_in_memory() -> Result { Ok(Self { db: sled::Config::new().temporary(true).open()?, + read_cache: Default::default(), }) } } @@ -91,6 +100,10 @@ impl StorageBackend for SledBackend { self.db.is_empty() } + fn get_read_cache(&self) -> RefMut { + self.read_cache.borrow_mut() + } + #[cfg(test)] fn len(&self) -> usize { self.db.len() diff --git a/storage/src/storage_auto_ptr.rs b/storage/src/storage_auto_ptr.rs index ae7bbf8..7c6256b 100644 --- a/storage/src/storage_auto_ptr.rs +++ b/storage/src/storage_auto_ptr.rs @@ -6,7 +6,7 @@ use crate::{StorageBackend, StorageEntity, StorageEntryPtr}; pub struct StorageAutoPtr> { pub(crate) _marker: std::marker::PhantomData, - pub(crate) sb: Weak>, // TODO: Does this need to be weak? + pub sb: Weak>, // TODO: Does this need to be weak? pub ptr: StorageEntryPtr, } diff --git a/storage/src/storage_backend.rs b/storage/src/storage_backend.rs index e89826f..cc2a341 100644 --- a/storage/src/storage_backend.rs +++ b/storage/src/storage_backend.rs @@ -1,12 +1,12 @@ use std::{ - cell::RefCell, + cell::{RefCell, RefMut}, error::Error, rc::{Rc, Weak}, }; use crate::{ storage_io::{StorageReader, StorageTxMut}, - GenericError, StoragePtr, + GenericError, ReadCache, StoragePtr, }; pub trait StorageBackend: Sized { @@ -30,6 +30,8 @@ pub trait StorageBackend: Sized { fn is_empty(&self) -> bool; + fn get_read_cache(&self) -> RefMut; + #[cfg(test)] fn len(&self) -> usize; } diff --git a/valuescript_vm/src/vs_storage_ptr.rs b/valuescript_vm/src/vs_storage_ptr.rs index e233986..f6f4d22 100644 --- a/valuescript_vm/src/vs_storage_ptr.rs +++ b/valuescript_vm/src/vs_storage_ptr.rs @@ -4,7 +4,7 @@ use std::{ rc::Rc, }; -use storage::{StorageAutoPtr, StorageBackend, StorageEntryPtr}; +use storage::{StorageAutoPtr, StorageBackend, StorageEntity, StorageEntryPtr, StorageReader}; use crate::vs_value::{ToVal, Val}; @@ -19,7 +19,26 @@ pub struct StorageValAutoPtr { impl ValResolver for StorageValAutoPtr { fn resolve(&self) -> Val { - self.ptr.resolve().unwrap().unwrap() + let sb = match self.ptr.sb.upgrade() { + Some(sb) => sb, + None => panic!("Storage backend dropped"), + }; + + let borrow = sb.borrow(); + let mut read_cache = borrow.get_read_cache(); + + if let Some(cache_box) = read_cache.get(&self.ptr.ptr.data) { + if let Some(cache_val) = cache_box.downcast_ref::() { + return cache_val.clone(); + } + } + + let entry = sb.read(self.ptr.ptr).unwrap().expect("Unresolved ptr"); + let res = Val::from_storage_entry(&sb, entry).expect("Failed to deserialize Val"); + + read_cache.insert(self.ptr.ptr.data, Box::new(res.clone())); + + res } fn ptr(&self) -> StorageEntryPtr {