From 536683e73b296b48b6f584bace47df6a3d5db936 Mon Sep 17 00:00:00 2001 From: Christian Ebner Date: Thu, 27 Feb 2020 15:56:28 +0100 Subject: [PATCH] src/backup/dynamic_index.rs: Add LruCache for chunks. In order to improve non-sequential reads of chunks as e.g. in FUSE. Signed-off-by: Christian Ebner --- src/backup/dynamic_index.rs | 34 +++++++++++++++++++++++++--------- src/tools/lru_cache.rs | 2 ++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/backup/dynamic_index.rs b/src/backup/dynamic_index.rs index 0a993d34..bc65da22 100644 --- a/src/backup/dynamic_index.rs +++ b/src/backup/dynamic_index.rs @@ -266,6 +266,19 @@ pub struct BufferedDynamicReader { buffered_chunk_idx: usize, buffered_chunk_start: u64, read_offset: u64, + lru_cache: crate::tools::lru_cache::LruCache)>, +} + +struct ChunkCacher<'a, S> { + store: &'a mut S, + index: &'a DynamicIndexReader, +} + +impl<'a, S: ReadChunk> crate::tools::lru_cache::Cacher)> for ChunkCacher<'a, S> { + fn fetch(&mut self, index: usize) -> Result)>, failure::Error> { + let (start, end, digest) = self.index.chunk_info(index)?; + self.store.read_chunk(&digest).and_then(|data| Ok(Some((start, end, data)))) + } } impl BufferedDynamicReader { @@ -279,6 +292,7 @@ impl BufferedDynamicReader { buffered_chunk_idx: 0, buffered_chunk_start: 0, read_offset: 0, + lru_cache: crate::tools::lru_cache::LruCache::new(32), } } @@ -287,27 +301,29 @@ impl BufferedDynamicReader { } fn buffer_chunk(&mut self, idx: usize) -> Result<(), Error> { - let index = &self.index; - let (start, end, digest) = index.chunk_info(idx)?; + let (start, end, data) = self.lru_cache.access( + idx, + &mut ChunkCacher { + store: &mut self.store, + index: &self.index, + }, + )?.ok_or_else(|| format_err!("chunk not found by cacher"))?; - // fixme: avoid copy - - let data = self.store.read_chunk(&digest)?; - - if (end - start) != data.len() as u64 { + if (*end - *start) != data.len() as u64 { bail!( "read chunk with wrong size ({} != {}", - (end - start), + (*end - *start), data.len() ); } + // fixme: avoid copy self.read_buffer.clear(); self.read_buffer.extend_from_slice(&data); self.buffered_chunk_idx = idx; - self.buffered_chunk_start = start as u64; + self.buffered_chunk_start = *start; //println!("BUFFER {} {}", self.buffered_chunk_start, end); Ok(()) } diff --git a/src/tools/lru_cache.rs b/src/tools/lru_cache.rs index cfcf0c00..1a73a59a 100644 --- a/src/tools/lru_cache.rs +++ b/src/tools/lru_cache.rs @@ -100,6 +100,8 @@ pub struct LruCache { _marker: PhantomData>>, } +unsafe impl Send for LruCache {} + impl LruCache { /// Create LRU cache instance which holds up to `capacity` nodes at once. pub fn new(capacity: usize) -> Self {