mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
perf: preset multi spotter only updates sizes for folders to cut memory usage (#3751)
This commit is contained in:
parent
741f84e22b
commit
8932ddd66d
9 changed files with 76 additions and 61 deletions
42
Cargo.lock
generated
42
Cargo.lock
generated
|
|
@ -1368,12 +1368,6 @@ dependencies = [
|
||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "env_home"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equator"
|
name = "equator"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
@ -1931,9 +1925,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hybrid-array"
|
name = "hybrid-array"
|
||||||
version = "0.4.7"
|
version = "0.4.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1b229d73f5803b562cc26e4da0396c8610a4ee209f4fac8fa4f8d709166dc45"
|
checksum = "8655f91cd07f2b9d0c24137bd650fe69617773435ee5ec83022377777ce65ef1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
@ -2231,9 +2225,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.182"
|
version = "0.2.183"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libcrux-intrinsics"
|
name = "libcrux-intrinsics"
|
||||||
|
|
@ -2551,9 +2545,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "moxcms"
|
name = "moxcms"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04e5f643aebb3c117fa77e268557e3bf19e250769062820fcaf3ff33ea560adf"
|
checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"pxfm",
|
"pxfm",
|
||||||
|
|
@ -5214,13 +5208,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "which"
|
name = "which"
|
||||||
version = "8.0.1"
|
version = "8.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a824aeba0fbb27264f815ada4cff43d65b1741b7a4ed7629ff9089148c4a4e0"
|
checksum = "81995fafaaaf6ae47a7d0cc83c67caf92aeb7e5331650ae6ff856f7c0c60c459"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_home",
|
"libc",
|
||||||
"rustix 1.1.4",
|
|
||||||
"winsafe",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -5598,12 +5590,6 @@ version = "0.7.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winsafe"
|
|
||||||
version = "0.0.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|
@ -5753,7 +5739,7 @@ dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"crossterm 0.29.0",
|
"crossterm 0.29.0",
|
||||||
"image",
|
"image",
|
||||||
"moxcms 0.8.0",
|
"moxcms 0.8.1",
|
||||||
"palette",
|
"palette",
|
||||||
"quantette",
|
"quantette",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
|
|
@ -6299,18 +6285,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.40"
|
version = "0.8.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5"
|
checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.40"
|
version = "0.8.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953"
|
checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ futures = "0.3.32"
|
||||||
globset = "0.4.18"
|
globset = "0.4.18"
|
||||||
hashbrown = { version = "0.16.1", features = [ "serde" ] }
|
hashbrown = { version = "0.16.1", features = [ "serde" ] }
|
||||||
indexmap = { version = "2.13.0", features = [ "serde" ] }
|
indexmap = { version = "2.13.0", features = [ "serde" ] }
|
||||||
libc = "0.2.182"
|
libc = "0.2.183"
|
||||||
lru = "0.16.3"
|
lru = "0.16.3"
|
||||||
mlua = { version = "0.11.6", features = [ "anyhow", "async", "error-send", "lua55", "macros", "serde" ] }
|
mlua = { version = "0.11.6", features = [ "anyhow", "async", "error-send", "lua55", "macros", "serde" ] }
|
||||||
objc2 = "0.6.4"
|
objc2 = "0.6.4"
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ anyhow = { workspace = true }
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
crossterm = { workspace = true }
|
crossterm = { workspace = true }
|
||||||
image = { version = "0.25.9", default-features = false, features = [ "avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "tiff", "webp" ] }
|
image = { version = "0.25.9", default-features = false, features = [ "avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "tiff", "webp" ] }
|
||||||
moxcms = "0.8.0"
|
moxcms = "0.8.1"
|
||||||
palette = { version = "0.7.6", default-features = false }
|
palette = { version = "0.7.6", default-features = false }
|
||||||
quantette = { version = "0.5.1", default-features = false }
|
quantette = { version = "0.5.1", default-features = false }
|
||||||
ratatui = { workspace = true }
|
ratatui = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use mlua::{IntoLuaMulti, UserData, UserDataMethods, Value};
|
use mlua::{IntoLuaMulti, UserData, UserDataFields, UserDataMethods, Value};
|
||||||
|
|
||||||
use crate::Error;
|
use crate::{Cha, Error};
|
||||||
|
|
||||||
pub enum SizeCalculator {
|
pub enum SizeCalculator {
|
||||||
Local(yazi_fs::provider::local::SizeCalculator),
|
Local(yazi_fs::provider::local::SizeCalculator),
|
||||||
|
|
@ -8,11 +8,20 @@ pub enum SizeCalculator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for SizeCalculator {
|
impl UserData for SizeCalculator {
|
||||||
|
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("cha", |_, me| {
|
||||||
|
Ok(Cha(match me {
|
||||||
|
Self::Local(c) => c.cha(),
|
||||||
|
Self::Remote(c) => c.cha(),
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||||
methods.add_async_method_mut("recv", |lua, mut me, ()| async move {
|
methods.add_async_method_mut("recv", |lua, mut me, ()| async move {
|
||||||
let next = match &mut *me {
|
let next = match &mut *me {
|
||||||
Self::Local(it) => it.next().await,
|
Self::Local(c) => c.next().await,
|
||||||
Self::Remote(it) => it.next().await,
|
Self::Remote(c) => c.next().await,
|
||||||
};
|
};
|
||||||
|
|
||||||
match next {
|
match next {
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,11 @@ impl Actions {
|
||||||
pub(super) fn debug() -> Result<String, std::fmt::Error> {
|
pub(super) fn debug() -> Result<String, std::fmt::Error> {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
writeln!(s, "\nYazi")?;
|
writeln!(s, "\nYazi")?;
|
||||||
writeln!(s, " Version: {}", Self::version())?;
|
writeln!(s, " Version : {}", Self::version())?;
|
||||||
writeln!(s, " Debug : {}", cfg!(debug_assertions))?;
|
writeln!(s, " Debug : {}", cfg!(debug_assertions))?;
|
||||||
writeln!(s, " Triple : {}", Self::triple())?;
|
writeln!(s, " Triple : {}", Self::triple())?;
|
||||||
writeln!(s, " Rustc : {}", Self::rustc())?;
|
writeln!(s, " Rustc : {}", Self::rustc())?;
|
||||||
|
writeln!(s, " Backtrace: {:?}", env::var_os("RUST_BACKTRACE"))?;
|
||||||
|
|
||||||
writeln!(s, "\nYa")?;
|
writeln!(s, "\nYa")?;
|
||||||
writeln!(s, " Version: {}", Self::process_output("ya", "--version"))?;
|
writeln!(s, " Version: {}", Self::process_output("ya", "--version"))?;
|
||||||
|
|
|
||||||
|
|
@ -3,29 +3,37 @@ use std::{collections::VecDeque, future::poll_fn, io, mem, path::{Path, PathBuf}
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
|
|
||||||
|
use crate::cha::Cha;
|
||||||
|
|
||||||
type Task = Either<PathBuf, std::fs::ReadDir>;
|
type Task = Either<PathBuf, std::fs::ReadDir>;
|
||||||
|
|
||||||
pub enum SizeCalculator {
|
pub enum SizeCalculator {
|
||||||
Idle((VecDeque<Task>, Option<u64>)),
|
Idle((VecDeque<Task>, Option<u64>), Cha),
|
||||||
Pending(JoinHandle<(VecDeque<Task>, Option<u64>)>),
|
Pending(JoinHandle<(VecDeque<Task>, Option<u64>)>, Cha),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeCalculator {
|
impl SizeCalculator {
|
||||||
pub async fn new(path: &Path) -> io::Result<Self> {
|
pub async fn new(path: &Path) -> io::Result<Self> {
|
||||||
let p = path.to_owned();
|
let p = path.to_owned();
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let meta = std::fs::symlink_metadata(&p)?;
|
let cha = Cha::new(p.file_name().unwrap_or_default(), std::fs::symlink_metadata(&p)?);
|
||||||
if !meta.is_dir() {
|
if !cha.is_dir() {
|
||||||
return Ok(Self::Idle((VecDeque::new(), Some(meta.len()))));
|
return Ok(Self::Idle((VecDeque::new(), Some(cha.len)), cha));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut buf = VecDeque::from([Either::Right(std::fs::read_dir(&p)?)]);
|
let mut buf = VecDeque::from([Either::Right(std::fs::read_dir(&p)?)]);
|
||||||
let size = Self::next_chunk(&mut buf);
|
let size = Self::next_chunk(&mut buf);
|
||||||
Ok(Self::Idle((buf, size)))
|
Ok(Self::Idle((buf, size), cha))
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cha(&self) -> Cha {
|
||||||
|
match *self {
|
||||||
|
Self::Idle(_, cha) | Self::Pending(_, cha) => cha,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn total(path: &Path) -> io::Result<u64> {
|
pub async fn total(path: &Path) -> io::Result<u64> {
|
||||||
let mut it = Self::new(path).await?;
|
let mut it = Self::new(path).await?;
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
|
|
@ -39,7 +47,7 @@ impl SizeCalculator {
|
||||||
poll_fn(|cx| {
|
poll_fn(|cx| {
|
||||||
loop {
|
loop {
|
||||||
match self {
|
match self {
|
||||||
Self::Idle((buf, size)) => {
|
Self::Idle((buf, size), cha) => {
|
||||||
if let Some(s) = size.take() {
|
if let Some(s) = size.take() {
|
||||||
return Poll::Ready(Ok(Some(s)));
|
return Poll::Ready(Ok(Some(s)));
|
||||||
} else if buf.is_empty() {
|
} else if buf.is_empty() {
|
||||||
|
|
@ -47,13 +55,16 @@ impl SizeCalculator {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut buf = mem::take(buf);
|
let mut buf = mem::take(buf);
|
||||||
*self = Self::Pending(tokio::task::spawn_blocking(move || {
|
*self = Self::Pending(
|
||||||
let size = Self::next_chunk(&mut buf);
|
tokio::task::spawn_blocking(move || {
|
||||||
(buf, size)
|
let size = Self::next_chunk(&mut buf);
|
||||||
}));
|
(buf, size)
|
||||||
|
}),
|
||||||
|
*cha,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Self::Pending(handle) => {
|
Self::Pending(handle, cha) => {
|
||||||
*self = Self::Idle(ready!(Pin::new(handle).poll(cx))?);
|
*self = Self::Idle(ready!(Pin::new(handle).poll(cx))?, *cha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ function M:spot(job)
|
||||||
|
|
||||||
local url = job.file.url
|
local url = job.file.url
|
||||||
local it = fs.calc_size(url)
|
local it = fs.calc_size(url)
|
||||||
while true do
|
while it do
|
||||||
local next = it:recv()
|
local next = it:recv()
|
||||||
if next then
|
if next then
|
||||||
self.size = self.size + next
|
self.size = self.size + next
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,15 @@ function M:spot(job)
|
||||||
|
|
||||||
for _, u in ipairs(self.selected) do
|
for _, u in ipairs(self.selected) do
|
||||||
local it, size = fs.calc_size(u), 0
|
local it, size = fs.calc_size(u), 0
|
||||||
while true do
|
while it do
|
||||||
local next = it:recv()
|
local next = it:recv()
|
||||||
if next then
|
if next then
|
||||||
size, self.sum = size + next, self.sum + next
|
size, self.sum = size + next, self.sum + next
|
||||||
self:spot_multi(job, false)
|
self:spot_multi(job, false)
|
||||||
|
elseif it.cha.is_dir then
|
||||||
|
self.sizes[u] = size
|
||||||
|
break
|
||||||
else
|
else
|
||||||
self.sizes[u], size = size, 0
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
use std::{collections::VecDeque, io, time::{Duration, Instant}};
|
use std::{collections::VecDeque, io, time::{Duration, Instant}};
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use yazi_fs::provider::{DirReader, FileHolder};
|
use yazi_fs::{cha::Cha, provider::{DirReader, FileHolder}};
|
||||||
use yazi_shared::url::{AsUrl, UrlBuf};
|
use yazi_shared::url::{AsUrl, UrlBuf};
|
||||||
|
|
||||||
use super::ReadDir;
|
use super::ReadDir;
|
||||||
|
|
||||||
pub enum SizeCalculator {
|
pub enum SizeCalculator {
|
||||||
File(Option<u64>),
|
File(Option<u64>, Cha),
|
||||||
Dir(VecDeque<Either<UrlBuf, ReadDir>>),
|
Dir(VecDeque<Either<UrlBuf, ReadDir>>, Cha),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeCalculator {
|
impl SizeCalculator {
|
||||||
|
|
@ -19,12 +19,18 @@ impl SizeCalculator {
|
||||||
let url = url.as_url();
|
let url = url.as_url();
|
||||||
let cha = super::symlink_metadata(url).await?;
|
let cha = super::symlink_metadata(url).await?;
|
||||||
Ok(if cha.is_dir() {
|
Ok(if cha.is_dir() {
|
||||||
Self::Dir(VecDeque::from([Either::Left(url.to_owned())]))
|
Self::Dir(VecDeque::from([Either::Left(url.to_owned())]), cha)
|
||||||
} else {
|
} else {
|
||||||
Self::File(Some(cha.len))
|
Self::File(Some(cha.len), cha)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cha(&self) -> Cha {
|
||||||
|
match *self {
|
||||||
|
Self::File(_, cha) | Self::Dir(_, cha) => cha,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn total<U>(url: U) -> io::Result<u64>
|
pub async fn total<U>(url: U) -> io::Result<u64>
|
||||||
where
|
where
|
||||||
U: AsUrl,
|
U: AsUrl,
|
||||||
|
|
@ -39,8 +45,8 @@ impl SizeCalculator {
|
||||||
|
|
||||||
pub async fn next(&mut self) -> io::Result<Option<u64>> {
|
pub async fn next(&mut self) -> io::Result<Option<u64>> {
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Self::File(size) => size.take(),
|
Self::File(size, _) => size.take(),
|
||||||
Self::Dir(buf) => Self::next_chunk(buf).await,
|
Self::Dir(buf, _) => Self::next_chunk(buf).await,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue