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
This commit is contained in:
parent
741f84e22b
commit
2c40342e0d
6 changed files with 60 additions and 31 deletions
|
|
@ -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 {
|
||||
Local(yazi_fs::provider::local::SizeCalculator),
|
||||
|
|
@ -8,11 +8,20 @@ pub enum 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) {
|
||||
methods.add_async_method_mut("recv", |lua, mut me, ()| async move {
|
||||
let next = match &mut *me {
|
||||
Self::Local(it) => it.next().await,
|
||||
Self::Remote(it) => it.next().await,
|
||||
Self::Local(c) => c.next().await,
|
||||
Self::Remote(c) => c.next().await,
|
||||
};
|
||||
|
||||
match next {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ impl Actions {
|
|||
pub(super) fn debug() -> Result<String, std::fmt::Error> {
|
||||
let mut s = String::new();
|
||||
writeln!(s, "\nYazi")?;
|
||||
writeln!(s, " Version: {}", Self::version())?;
|
||||
writeln!(s, " Debug : {}", cfg!(debug_assertions))?;
|
||||
writeln!(s, " Triple : {}", Self::triple())?;
|
||||
writeln!(s, " Rustc : {}", Self::rustc())?;
|
||||
writeln!(s, " Version : {}", Self::version())?;
|
||||
writeln!(s, " Debug : {}", cfg!(debug_assertions))?;
|
||||
writeln!(s, " Triple : {}", Self::triple())?;
|
||||
writeln!(s, " Rustc : {}", Self::rustc())?;
|
||||
writeln!(s, " Backtrace: {:?}", env::var_os("RUST_BACKTRACE"))?;
|
||||
|
||||
writeln!(s, "\nYa")?;
|
||||
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 tokio::task::JoinHandle;
|
||||
|
||||
use crate::cha::Cha;
|
||||
|
||||
type Task = Either<PathBuf, std::fs::ReadDir>;
|
||||
|
||||
pub enum SizeCalculator {
|
||||
Idle((VecDeque<Task>, Option<u64>)),
|
||||
Pending(JoinHandle<(VecDeque<Task>, Option<u64>)>),
|
||||
Idle((VecDeque<Task>, Option<u64>), Cha),
|
||||
Pending(JoinHandle<(VecDeque<Task>, Option<u64>)>, Cha),
|
||||
}
|
||||
|
||||
impl SizeCalculator {
|
||||
pub async fn new(path: &Path) -> io::Result<Self> {
|
||||
let p = path.to_owned();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let meta = std::fs::symlink_metadata(&p)?;
|
||||
if !meta.is_dir() {
|
||||
return Ok(Self::Idle((VecDeque::new(), Some(meta.len()))));
|
||||
let cha = Cha::new(p.file_name().unwrap_or_default(), std::fs::symlink_metadata(&p)?);
|
||||
if !cha.is_dir() {
|
||||
return Ok(Self::Idle((VecDeque::new(), Some(cha.len)), cha));
|
||||
}
|
||||
|
||||
let mut buf = VecDeque::from([Either::Right(std::fs::read_dir(&p)?)]);
|
||||
let size = Self::next_chunk(&mut buf);
|
||||
Ok(Self::Idle((buf, size)))
|
||||
Ok(Self::Idle((buf, size), cha))
|
||||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
pub fn cha(&self) -> Cha {
|
||||
match *self {
|
||||
Self::Idle(_, cha) | Self::Pending(_, cha) => cha,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn total(path: &Path) -> io::Result<u64> {
|
||||
let mut it = Self::new(path).await?;
|
||||
let mut total = 0;
|
||||
|
|
@ -39,7 +47,7 @@ impl SizeCalculator {
|
|||
poll_fn(|cx| {
|
||||
loop {
|
||||
match self {
|
||||
Self::Idle((buf, size)) => {
|
||||
Self::Idle((buf, size), cha) => {
|
||||
if let Some(s) = size.take() {
|
||||
return Poll::Ready(Ok(Some(s)));
|
||||
} else if buf.is_empty() {
|
||||
|
|
@ -47,13 +55,16 @@ impl SizeCalculator {
|
|||
}
|
||||
|
||||
let mut buf = mem::take(buf);
|
||||
*self = Self::Pending(tokio::task::spawn_blocking(move || {
|
||||
let size = Self::next_chunk(&mut buf);
|
||||
(buf, size)
|
||||
}));
|
||||
*self = Self::Pending(
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let size = Self::next_chunk(&mut buf);
|
||||
(buf, size)
|
||||
}),
|
||||
*cha,
|
||||
);
|
||||
}
|
||||
Self::Pending(handle) => {
|
||||
*self = Self::Idle(ready!(Pin::new(handle).poll(cx))?);
|
||||
Self::Pending(handle, cha) => {
|
||||
*self = Self::Idle(ready!(Pin::new(handle).poll(cx))?, *cha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ function M:spot(job)
|
|||
|
||||
local url = job.file.url
|
||||
local it = fs.calc_size(url)
|
||||
while true do
|
||||
while it do
|
||||
local next = it:recv()
|
||||
if next then
|
||||
self.size = self.size + next
|
||||
|
|
|
|||
|
|
@ -14,13 +14,15 @@ function M:spot(job)
|
|||
|
||||
for _, u in ipairs(self.selected) do
|
||||
local it, size = fs.calc_size(u), 0
|
||||
while true do
|
||||
while it do
|
||||
local next = it:recv()
|
||||
if next then
|
||||
size, self.sum = size + next, self.sum + next
|
||||
self:spot_multi(job, false)
|
||||
elseif it.cha.is_dir then
|
||||
self.sizes[u] = size
|
||||
break
|
||||
else
|
||||
self.sizes[u], size = size, 0
|
||||
break
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use std::{collections::VecDeque, io, time::{Duration, Instant}};
|
||||
|
||||
use either::Either;
|
||||
use yazi_fs::provider::{DirReader, FileHolder};
|
||||
use yazi_fs::{cha::Cha, provider::{DirReader, FileHolder}};
|
||||
use yazi_shared::url::{AsUrl, UrlBuf};
|
||||
|
||||
use super::ReadDir;
|
||||
|
||||
pub enum SizeCalculator {
|
||||
File(Option<u64>),
|
||||
Dir(VecDeque<Either<UrlBuf, ReadDir>>),
|
||||
File(Option<u64>, Cha),
|
||||
Dir(VecDeque<Either<UrlBuf, ReadDir>>, Cha),
|
||||
}
|
||||
|
||||
impl SizeCalculator {
|
||||
|
|
@ -19,12 +19,18 @@ impl SizeCalculator {
|
|||
let url = url.as_url();
|
||||
let cha = super::symlink_metadata(url).await?;
|
||||
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 {
|
||||
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>
|
||||
where
|
||||
U: AsUrl,
|
||||
|
|
@ -39,8 +45,8 @@ impl SizeCalculator {
|
|||
|
||||
pub async fn next(&mut self) -> io::Result<Option<u64>> {
|
||||
Ok(match self {
|
||||
Self::File(size) => size.take(),
|
||||
Self::Dir(buf) => Self::next_chunk(buf).await,
|
||||
Self::File(size, _) => size.take(),
|
||||
Self::Dir(buf, _) => Self::next_chunk(buf).await,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue