From 920afe29bde957fdaf52bd14a6ec17387e7e43f8 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Thu, 1 Feb 2024 18:43:59 +0800 Subject: [PATCH] perf: use lazy sorting when loading large directories to reduce unnecessary CPU consumption (#607) --- yazi-core/src/folder/folder.rs | 15 ++++++++++++--- yazi-core/src/folder/mod.rs | 2 ++ yazi-core/src/folder/stage.rs | 7 +++++++ yazi-core/src/manager/commands/unyank.rs | 3 ++- yazi-core/src/tab/preview.rs | 2 +- yazi-core/src/tab/tab.rs | 8 ++++++-- 6 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 yazi-core/src/folder/stage.rs diff --git a/yazi-core/src/folder/folder.rs b/yazi-core/src/folder/folder.rs index 6d5b714e..49fd1c34 100644 --- a/yazi-core/src/folder/folder.rs +++ b/yazi-core/src/folder/folder.rs @@ -4,13 +4,15 @@ use ratatui::layout::Rect; use yazi_config::LAYOUT; use yazi_shared::fs::{File, FilesOp, Url}; +use super::FolderStage; use crate::{folder::Files, manager::Manager, Step}; #[derive(Default)] pub struct Folder { pub cwd: Url, - pub mtime: Option, pub files: Files, + pub mtime: Option, + pub stage: FolderStage, pub offset: usize, pub cursor: usize, @@ -31,8 +33,15 @@ impl Folder { pub fn update(&mut self, op: FilesOp) -> bool { let revision = self.files.revision; match op { - FilesOp::Full(_, _, mtime) => self.mtime = mtime, - FilesOp::Done(_, mtime, ticket) if ticket == self.files.ticket() => self.mtime = mtime, + FilesOp::Full(_, _, mtime) => { + (self.mtime, self.stage) = (mtime, FolderStage::Loaded); + } + FilesOp::Part(_, _, ticket) if ticket == self.files.ticket() => { + self.stage = FolderStage::Loading; + } + FilesOp::Done(_, mtime, ticket) if ticket == self.files.ticket() => { + (self.mtime, self.stage) = (mtime, FolderStage::Loaded); + } _ => {} } diff --git a/yazi-core/src/folder/mod.rs b/yazi-core/src/folder/mod.rs index e6bce8d1..1acfc9f4 100644 --- a/yazi-core/src/folder/mod.rs +++ b/yazi-core/src/folder/mod.rs @@ -2,8 +2,10 @@ mod files; mod filter; mod folder; mod sorter; +mod stage; pub use files::*; pub use filter::*; pub use folder::*; pub use sorter::*; +pub use stage::*; diff --git a/yazi-core/src/folder/stage.rs b/yazi-core/src/folder/stage.rs new file mode 100644 index 00000000..bd8a3674 --- /dev/null +++ b/yazi-core/src/folder/stage.rs @@ -0,0 +1,7 @@ +#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] +pub enum FolderStage { + #[default] + Loading, + Loaded, + Failed, +} diff --git a/yazi-core/src/manager/commands/unyank.rs b/yazi-core/src/manager/commands/unyank.rs index 8eaa81f9..918223f0 100644 --- a/yazi-core/src/manager/commands/unyank.rs +++ b/yazi-core/src/manager/commands/unyank.rs @@ -4,7 +4,8 @@ use crate::manager::Manager; impl Manager { pub fn unyank(&mut self, _: Cmd) { + render!(!self.yanked.1.is_empty()); + self.yanked = Default::default(); - render!(); } } diff --git a/yazi-core/src/tab/preview.rs b/yazi-core/src/tab/preview.rs index 60fa3ddf..e24a7834 100644 --- a/yazi-core/src/tab/preview.rs +++ b/yazi-core/src/tab/preview.rs @@ -73,7 +73,7 @@ impl Preview { }; let stream = - UnboundedReceiverStream::new(rx).chunks_timeout(10000, Duration::from_millis(350)); + UnboundedReceiverStream::new(rx).chunks_timeout(50000, Duration::from_millis(500)); pin!(stream); let ticket = FilesOp::prepare(&url); diff --git a/yazi-core/src/tab/tab.rs b/yazi-core/src/tab/tab.rs index c431c404..6266d03e 100644 --- a/yazi-core/src/tab/tab.rs +++ b/yazi-core/src/tab/tab.rs @@ -5,7 +5,7 @@ use tokio::task::JoinHandle; use yazi_shared::{fs::{File, Url}, render}; use super::{Backstack, Config, Finder, Mode, Preview}; -use crate::folder::Folder; +use crate::folder::{Folder, FolderStage}; pub struct Tab { pub mode: Mode, @@ -74,10 +74,14 @@ impl Tab { pub fn apply_files_attrs(&mut self) { let apply = |f: &mut Folder| { - let hovered = f.hovered().filter(|_| f.tracing).map(|h| h.url()); + if f.stage == FolderStage::Loading { + return render!(); + } + let hovered = f.hovered().filter(|_| f.tracing).map(|h| h.url()); f.files.set_show_hidden(self.conf.show_hidden); f.files.set_sorter(self.conf.sorter()); + render!(f.files.catchup_revision()); render!(f.repos(hovered)); };