mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
perf: precache small images to avoid cache misses; use symlink_metadata instead of metadata (#367)
This commit is contained in:
parent
5968b82b0e
commit
ff30b244b1
10 changed files with 16 additions and 30 deletions
|
|
@ -170,7 +170,7 @@ impl Adaptor {
|
||||||
|
|
||||||
pub async fn image_show(self, mut path: &Path, rect: Rect) -> Result<()> {
|
pub async fn image_show(self, mut path: &Path, rect: Rect) -> Result<()> {
|
||||||
let cache = PREVIEW.cache(path, 0);
|
let cache = PREVIEW.cache(path, 0);
|
||||||
if fs::metadata(&cache).await.is_ok() {
|
if fs::symlink_metadata(&cache).await.is_ok() {
|
||||||
path = cache.as_path();
|
path = cache.as_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use yazi_shared::Term;
|
||||||
pub struct Image;
|
pub struct Image;
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
pub(super) async fn crop(path: &Path, size: (u16, u16)) -> Result<DynamicImage> {
|
pub(super) async fn downscale(path: &Path, size: (u16, u16)) -> Result<DynamicImage> {
|
||||||
let (w, h) = Term::ratio()
|
let (w, h) = Term::ratio()
|
||||||
.map(|(w, h)| {
|
.map(|(w, h)| {
|
||||||
let (w, h) = ((size.0 as f64 * w) as u32, (size.1 as f64 * h) as u32);
|
let (w, h) = ((size.0 as f64 * w) as u32, (size.1 as f64 * h) as u32);
|
||||||
|
|
@ -30,33 +30,19 @@ impl Image {
|
||||||
img.await?
|
img.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn precache(img: Arc<Vec<u8>>, cache: impl AsRef<Path>) -> Result<bool> {
|
pub async fn precache(img: Arc<Vec<u8>>, cache: impl AsRef<Path>) -> Result<()> {
|
||||||
let cache = cache.as_ref().to_owned();
|
let cache = cache.as_ref().to_owned();
|
||||||
let result = tokio::task::spawn_blocking(move || {
|
let result = tokio::task::spawn_blocking(move || {
|
||||||
let img = image::load_from_memory(&img)?;
|
let img = image::load_from_memory(&img)?;
|
||||||
let (w, h) = (PREVIEW.max_width, PREVIEW.max_height);
|
let (w, h) = (PREVIEW.max_width, PREVIEW.max_height);
|
||||||
|
|
||||||
if img.width() <= w && img.height() <= h {
|
Ok(match img.resize(w, h, FilterType::Triangle) {
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
match img.resize(w, h, FilterType::Triangle) {
|
|
||||||
DynamicImage::ImageRgb8(buf) => buf.save_with_format(cache, ImageFormat::Jpeg),
|
DynamicImage::ImageRgb8(buf) => buf.save_with_format(cache, ImageFormat::Jpeg),
|
||||||
DynamicImage::ImageRgba8(buf) => buf.save_with_format(cache, ImageFormat::Jpeg),
|
DynamicImage::ImageRgba8(buf) => buf.save_with_format(cache, ImageFormat::Jpeg),
|
||||||
buf => buf.to_rgb8().save_with_format(cache, ImageFormat::Jpeg),
|
buf => buf.to_rgb8().save_with_format(cache, ImageFormat::Jpeg),
|
||||||
}?;
|
}?)
|
||||||
|
|
||||||
Ok(true)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
result.await?
|
result.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub async fn precache_anyway(img: Arc<Vec<u8>>, cache: impl AsRef<Path>) -> Result<()> {
|
|
||||||
Ok(match Self::precache(img.clone(), &cache).await {
|
|
||||||
Ok(true) => (),
|
|
||||||
_ => fs::write(cache, &*img).await?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ pub(super) struct Iterm2;
|
||||||
|
|
||||||
impl Iterm2 {
|
impl Iterm2 {
|
||||||
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
||||||
let img = Image::crop(path, (rect.width, rect.height)).await?;
|
let img = Image::downscale(path, (rect.width, rect.height)).await?;
|
||||||
let b = Self::encode(img).await?;
|
let b = Self::encode(img).await?;
|
||||||
|
|
||||||
Self::image_hide(rect)?;
|
Self::image_hide(rect)?;
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,7 @@ pub(super) struct Kitty;
|
||||||
|
|
||||||
impl Kitty {
|
impl Kitty {
|
||||||
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
||||||
let img = Image::crop(path, (rect.width, rect.height)).await?;
|
let img = Image::downscale(path, (rect.width, rect.height)).await?;
|
||||||
let b = Self::encode(img).await?;
|
let b = Self::encode(img).await?;
|
||||||
|
|
||||||
Self::image_hide(rect)?;
|
Self::image_hide(rect)?;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ pub(super) struct KittyOld;
|
||||||
|
|
||||||
impl KittyOld {
|
impl KittyOld {
|
||||||
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
||||||
let img = Image::crop(path, (rect.width, rect.height)).await?;
|
let img = Image::downscale(path, (rect.width, rect.height)).await?;
|
||||||
let b = Self::encode(img).await?;
|
let b = Self::encode(img).await?;
|
||||||
|
|
||||||
Self::image_hide()?;
|
Self::image_hide()?;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pub(super) struct Sixel;
|
||||||
|
|
||||||
impl Sixel {
|
impl Sixel {
|
||||||
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
|
||||||
let img = Image::crop(path, (rect.width, rect.height)).await?;
|
let img = Image::downscale(path, (rect.width, rect.height)).await?;
|
||||||
let b = Self::encode(img).await?;
|
let b = Self::encode(img).await?;
|
||||||
|
|
||||||
Self::image_hide(rect)?;
|
Self::image_hide(rect)?;
|
||||||
|
|
|
||||||
2
yazi-core/src/external/pdftoppm.rs
vendored
2
yazi-core/src/external/pdftoppm.rs
vendored
|
|
@ -25,5 +25,5 @@ pub async fn pdftoppm(src: &Path, dest: impl AsRef<Path>, skip: usize) -> Result
|
||||||
return if pages > 0 { Err(PeekError::Exceed(pages - 1)) } else { Err(s.to_string().into()) };
|
return if pages > 0 { Err(PeekError::Exceed(pages - 1)) } else { Err(s.to_string().into()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Image::precache_anyway(Arc::new(output.stdout), dest).await?)
|
Ok(Image::precache(Arc::new(output.stdout), dest).await?)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ impl Manager {
|
||||||
|
|
||||||
let mut failed = Vec::new();
|
let mut failed = Vec::new();
|
||||||
for (o, n) in todo {
|
for (o, n) in todo {
|
||||||
if fs::metadata(&n).await.is_ok() {
|
if fs::symlink_metadata(&n).await.is_ok() {
|
||||||
failed.push((o, n, anyhow!("Destination already exists")));
|
failed.push((o, n, anyhow!("Destination already exists")));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ impl Provider {
|
||||||
|
|
||||||
pub(super) async fn video(path: &Path, skip: usize) -> Result<PreviewData, PeekError> {
|
pub(super) async fn video(path: &Path, skip: usize) -> Result<PreviewData, PeekError> {
|
||||||
let cache = PREVIEW.cache(path, skip);
|
let cache = PREVIEW.cache(path, skip);
|
||||||
if fs::metadata(&cache).await.is_err() {
|
if fs::symlink_metadata(&cache).await.is_err() {
|
||||||
external::ffmpegthumbnailer(path, &cache, skip).await?;
|
external::ffmpegthumbnailer(path, &cache, skip).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +57,7 @@ impl Provider {
|
||||||
|
|
||||||
pub(super) async fn pdf(path: &Path, skip: usize) -> Result<PreviewData, PeekError> {
|
pub(super) async fn pdf(path: &Path, skip: usize) -> Result<PreviewData, PeekError> {
|
||||||
let cache = PREVIEW.cache(path, skip);
|
let cache = PREVIEW.cache(path, skip);
|
||||||
if fs::metadata(&cache).await.is_err() {
|
if fs::symlink_metadata(&cache).await.is_err() {
|
||||||
external::pdftoppm(path, &cache, skip).await?;
|
external::pdftoppm(path, &cache, skip).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ impl Precache {
|
||||||
match task {
|
match task {
|
||||||
PrecacheOp::Image(task) => {
|
PrecacheOp::Image(task) => {
|
||||||
let cache = PREVIEW.cache(&task.target, 0);
|
let cache = PREVIEW.cache(&task.target, 0);
|
||||||
if fs::metadata(&cache).await.is_ok() {
|
if fs::symlink_metadata(&cache).await.is_ok() {
|
||||||
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
|
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
|
||||||
}
|
}
|
||||||
if let Ok(img) = fs::read(&task.target).await {
|
if let Ok(img) = fs::read(&task.target).await {
|
||||||
|
|
@ -85,7 +85,7 @@ impl Precache {
|
||||||
}
|
}
|
||||||
PrecacheOp::Video(task) => {
|
PrecacheOp::Video(task) => {
|
||||||
let cache = PREVIEW.cache(&task.target, 0);
|
let cache = PREVIEW.cache(&task.target, 0);
|
||||||
if fs::metadata(&cache).await.is_ok() {
|
if fs::symlink_metadata(&cache).await.is_ok() {
|
||||||
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
|
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ impl Precache {
|
||||||
}
|
}
|
||||||
PrecacheOp::Pdf(task) => {
|
PrecacheOp::Pdf(task) => {
|
||||||
let cache = PREVIEW.cache(&task.target, 0);
|
let cache = PREVIEW.cache(&task.target, 0);
|
||||||
if fs::metadata(&cache).await.is_ok() {
|
if fs::symlink_metadata(&cache).await.is_ok() {
|
||||||
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
|
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue