summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2024-08-13 17:06:07 +1200
committerBen Bridle <bridle.benjamin@gmail.com>2024-08-13 17:06:07 +1200
commit05326e69658bfcb0e857988bc3ddfa9b2655ec52 (patch)
tree488af51eb33a2b72cde5a6e28b1f4f199b02659b
parent68f633f6ba35a4fbbae9ed22fc759ce3544f6a0e (diff)
downloadbedrock-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.rs20
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),
_ => (),