diff options
author | Ben Bridle <bridle.benjamin@gmail.com> | 2024-08-13 17:06:07 +1200 |
---|---|---|
committer | Ben Bridle <bridle.benjamin@gmail.com> | 2024-08-13 17:06:07 +1200 |
commit | 05326e69658bfcb0e857988bc3ddfa9b2655ec52 (patch) | |
tree | 488af51eb33a2b72cde5a6e28b1f4f199b02659b | |
parent | 68f633f6ba35a4fbbae9ed22fc759ce3544f6a0e (diff) | |
download | bedrock-pc-05326e69658bfcb0e857988bc3ddfa9b2655ec52.zip |
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.
-rw-r--r-- | src/devices/file.rs | 20 |
1 files 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), _ => (), |