From 1f0817080eb5448297c9c92bd9d729d76592dffc Mon Sep 17 00:00:00 2001 From: sxyazi Date: Thu, 28 Nov 2024 01:29:50 +0800 Subject: [PATCH] perf: introduce copy-on-write for event system to eliminate all memory reallocations --- yazi-fm/src/input/input.rs | 2 +- yazi-plugin/preset/plugins/font.lua | 11 ++++----- yazi-plugin/preset/plugins/magick.lua | 11 ++++----- yazi-plugin/preset/plugins/video.lua | 11 ++++----- yazi-plugin/src/external/highlighter.rs | 33 ++++++++++++++----------- yazi-proxy/src/options/plugin.rs | 2 +- yazi-shared/src/event/cmd.rs | 2 +- yazi-shared/src/event/data.rs | 2 +- 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/yazi-fm/src/input/input.rs b/yazi-fm/src/input/input.rs index eb17a3b15..d247d97ca 100644 --- a/yazi-fm/src/input/input.rs +++ b/yazi-fm/src/input/input.rs @@ -21,7 +21,7 @@ impl<'a> Input<'a> { bail!("Highlighting is disabled"); } - let (theme, syntaxes) = Highlighter::init(); + let (theme, syntaxes) = futures::executor::block_on(Highlighter::init()); if let Some(syntax) = syntaxes.find_syntax_by_name("Bourne Again Shell (bash)") { let mut h = HighlightLines::new(syntax, theme); let regions = h.highlight_line(self.cx.input.value(), syntaxes)?; diff --git a/yazi-plugin/preset/plugins/font.lua b/yazi-plugin/preset/plugins/font.lua index bf09650cb..567d72a2a 100644 --- a/yazi-plugin/preset/plugins/font.lua +++ b/yazi-plugin/preset/plugins/font.lua @@ -21,7 +21,7 @@ function M:preload() return 1 end - local child, err = Command("magick"):args({ + local status, err = Command("magick"):args({ "-size", "800x560", "-gravity", @@ -37,15 +37,14 @@ function M:preload() "+0+0", TEXT, "JPG:" .. tostring(cache), - }):spawn() + }):status() - if not child then + if status then + return status.success and 1 or 2 + else ya.err("Failed to start `magick`, error: " .. err) return 0 end - - local status = child:wait() - return status and status.success and 1 or 2 end return M diff --git a/yazi-plugin/preset/plugins/magick.lua b/yazi-plugin/preset/plugins/magick.lua index f260ebc6c..f74387dfc 100644 --- a/yazi-plugin/preset/plugins/magick.lua +++ b/yazi-plugin/preset/plugins/magick.lua @@ -19,7 +19,7 @@ function M:preload() return 1 end - local child, err = Command("magick"):args({ + local status, err = Command("magick"):args({ "-density", "200", tostring(self.file.url), @@ -30,15 +30,14 @@ function M:preload() tostring(PREVIEW.image_quality), "-auto-orient", "JPG:" .. tostring(cache), - }):spawn() + }):status() - if not child then + if status then + return status.success and 1 or 2 + else ya.err("Failed to start `magick`, error: " .. err) return 0 end - - local status = child:wait() - return status and status.success and 1 or 2 end function M:spot(job) require("file"):spot(job) end diff --git a/yazi-plugin/preset/plugins/video.lua b/yazi-plugin/preset/plugins/video.lua index 22f728099..c93a3f87b 100644 --- a/yazi-plugin/preset/plugins/video.lua +++ b/yazi-plugin/preset/plugins/video.lua @@ -49,7 +49,7 @@ function M:preload() local ss = math.floor(meta.format.duration * percent / 100) local qv = 31 - math.floor(PREVIEW.image_quality * 0.3) -- stylua: ignore - local child, err = Command("ffmpeg"):args({ + local status, err = Command("ffmpeg"):args({ "-v", "quiet", "-hwaccel", "auto", "-skip_frame", "nokey", "-ss", ss, "-an", "-sn", "-dn", @@ -59,15 +59,14 @@ function M:preload() "-vf", string.format("scale=%d:-2:flags=fast_bilinear", PREVIEW.max_width), "-f", "image2", "-y", tostring(cache), - }):spawn() + }):status() - if not child then + if status then + return status.success and 1 or 2 + else ya.err("Failed to start `ffmpeg`, error: " .. err) return 0 end - - local status = child:wait() - return status and status.success and 1 or 2 end function M:spot(job) diff --git a/yazi-plugin/src/external/highlighter.rs b/yazi-plugin/src/external/highlighter.rs index 75d379373..ab5b79f26 100644 --- a/yazi-plugin/src/external/highlighter.rs +++ b/yazi-plugin/src/external/highlighter.rs @@ -1,14 +1,14 @@ -use std::{borrow::Cow, io::Cursor, mem, path::{Path, PathBuf}, sync::OnceLock}; +use std::{borrow::Cow, io::Cursor, mem, path::{Path, PathBuf}}; use anyhow::{Result, anyhow}; use ratatui::{layout::Size, text::{Line, Span, Text}}; use syntect::{LoadingError, dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}}; -use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}}; +use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, sync::OnceCell}; use yazi_config::{PREVIEW, THEME, preview::PreviewWrap}; use yazi_shared::{Ids, errors::PeekError, replace_to_printable}; static INCR: Ids = Ids::new(); -static SYNTECT: OnceLock<(Theme, SyntaxSet)> = OnceLock::new(); +static SYNTECT: OnceCell<(Theme, SyntaxSet)> = OnceCell::const_new(); pub struct Highlighter { path: PathBuf, @@ -18,19 +18,22 @@ impl Highlighter { #[inline] pub fn new(path: &Path) -> Self { Self { path: path.to_owned() } } - pub fn init() -> (&'static Theme, &'static SyntaxSet) { - let r = SYNTECT.get_or_init(|| { - let theme = std::fs::File::open(&THEME.manager.syntect_theme) - .map_err(LoadingError::Io) - .and_then(|f| ThemeSet::load_from_reader(&mut std::io::BufReader::new(f))) - .or_else(|_| ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuild::ansi_theme()))); + pub async fn init() -> (&'static Theme, &'static SyntaxSet) { + let f = || { + tokio::task::spawn_blocking(|| { + let theme = std::fs::File::open(&THEME.manager.syntect_theme) + .map_err(LoadingError::Io) + .and_then(|f| ThemeSet::load_from_reader(&mut std::io::BufReader::new(f))) + .or_else(|_| ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuild::ansi_theme()))); - let syntaxes = dumps::from_uncompressed_data(yazi_prebuild::syntaxes()); + let syntaxes = dumps::from_uncompressed_data(yazi_prebuild::syntaxes()); - (theme.unwrap(), syntaxes.unwrap()) - }); + (theme.unwrap(), syntaxes.unwrap()) + }) + }; - (&r.0, &r.1) + let (theme, syntaxes) = SYNTECT.get_or_try_init(f).await.unwrap(); + (theme, syntaxes) } #[inline] @@ -100,7 +103,7 @@ impl Highlighter { syntax: &'static SyntaxReference, ) -> Result, PeekError> { let ticket = INCR.current(); - let (theme, syntaxes) = Self::init(); + let (theme, syntaxes) = Self::init().await; tokio::task::spawn_blocking(move || { let mut h = HighlightLines::new(syntax, theme); @@ -128,7 +131,7 @@ impl Highlighter { } async fn find_syntax(path: &Path) -> Result<&'static SyntaxReference> { - let (_, syntaxes) = Self::init(); + let (_, syntaxes) = Self::init().await; let name = path.file_name().map(|n| n.to_string_lossy()).unwrap_or_default(); if let Some(s) = syntaxes.find_syntax_by_extension(&name) { return Ok(s); diff --git a/yazi-proxy/src/options/plugin.rs b/yazi-proxy/src/options/plugin.rs index 77a19f2b0..afc0be60b 100644 --- a/yazi-proxy/src/options/plugin.rs +++ b/yazi-proxy/src/options/plugin.rs @@ -2,7 +2,7 @@ use anyhow::bail; use mlua::{Lua, Table}; use yazi_shared::event::{Cmd, Data}; -pub type PluginCallback = Box mlua::Result<()> + Send>; +pub type PluginCallback = Box mlua::Result<()> + Send + Sync>; #[derive(Default)] pub struct PluginOpt { diff --git a/yazi-shared/src/event/cmd.rs b/yazi-shared/src/event/cmd.rs index 307da56ad..c9baad82d 100644 --- a/yazi-shared/src/event/cmd.rs +++ b/yazi-shared/src/event/cmd.rs @@ -49,7 +49,7 @@ impl Cmd { } #[inline] - pub fn with_any(mut self, name: impl ToString, data: impl Any + Send) -> Self { + pub fn with_any(mut self, name: impl ToString, data: impl Any + Send + Sync) -> Self { self.args.insert(name.to_string(), Data::Any(Box::new(data))); self } diff --git a/yazi-shared/src/event/data.rs b/yazi-shared/src/event/data.rs index e5675a983..918caa6f3 100644 --- a/yazi-shared/src/event/data.rs +++ b/yazi-shared/src/event/data.rs @@ -18,7 +18,7 @@ pub enum Data { #[serde(skip_deserializing)] Url(Url), #[serde(skip)] - Any(Box), + Any(Box), } impl Data {