From 05326e69658bfcb0e857988bc3ddfa9b2655ec52 Mon Sep 17 00:00:00 2001 From: Ben Bridle Date: Tue, 13 Aug 2024 17:06:07 +1200 Subject: Improve performance of hierarchical file navigation The most recently closed directory listing is cached instead of being discarded. The next time a directory is to be opened, if the file path is the same as the cached directory, the cached directory listing is used in order to save the entire listing from having to be regenerated. This is expected to result in performance gains on Windows. --- src/devices/file.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/devices/file.rs b/src/devices/file.rs index bf185d7..0bea2f4 100644 --- a/src/devices/file.rs +++ b/src/devices/file.rs @@ -13,6 +13,7 @@ pub use entry::*; use operations::*; use std::path::{Component, Path, PathBuf}; +use std::mem::take; pub struct FileDevice { @@ -24,6 +25,7 @@ pub struct FileDevice { pub name_buffer: CircularPathBuffer, pub entry: Option<(Entry, BedrockFilePath)>, + pub cached_dir: Option<(Entry, BedrockFilePath)>, pub success: bool, pub pointer: u32, @@ -55,6 +57,7 @@ impl FileDevice { name_buffer: CircularPathBuffer::new(), entry: None, + cached_dir: None, success: false, pointer: 0, @@ -81,9 +84,11 @@ impl FileDevice { self.move_buffer.clear(); self.name_buffer.clear(); self.flush_entry(); - self.entry = None; self.pointer = 0; self.length = 0; + if let Some((Entry::Directory(dir), path)) = take(&mut self.entry) { + self.cached_dir = Some((Entry::Directory(dir), path)); + } } /// Process a byte received from the OPEN port. @@ -113,6 +118,15 @@ impl FileDevice { }; } Some(EntryType::Directory) => { + // Attempt to use the cached directory. + if let Some((dir, cached_path)) = take(&mut self.cached_dir) { + if cached_path == path { + self.close_entry(); + self.name_buffer.populate(cached_path.as_buffer()); + self.entry = Some((dir, cached_path)); + return Ok(()); + } + } // Keep the current entry open if we can't open the new path. if let Some(listing) = DirectoryListing::from_path(&path) { self.close_entry(); @@ -242,7 +256,7 @@ impl FileDevice { } pub fn commit_pointer(&mut self) { - let pointer = std::mem::take(&mut self.pointer); + let pointer = take(&mut self.pointer); match &mut self.entry { Some((Entry::File(buffered_file), _)) => buffered_file.set_pointer(pointer), Some((Entry::Directory(listing), _)) => listing.set_selected(pointer), @@ -259,7 +273,7 @@ impl FileDevice { } pub fn commit_length(&mut self) { - let length = std::mem::take(&mut self.length); + let length = take(&mut self.length); match &mut self.entry { Some((Entry::File(buffered_file), _)) => buffered_file.set_length(length), _ => (), -- cgit v1.2.3-70-g09d2