Skip to content

Commit

Permalink
perf: port require() and ya.sync() to Rust to avoid plugin inform…
Browse files Browse the repository at this point in the history
…ation initialization process (#853)
  • Loading branch information
sxyazi authored Mar 30, 2024
1 parent 903f3da commit c240602
Show file tree
Hide file tree
Showing 23 changed files with 310 additions and 152 deletions.
2 changes: 1 addition & 1 deletion cspell.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"0.2","language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub"]}
{"version":"0.2","words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers"],"language":"en","flagWords":[]}
4 changes: 2 additions & 2 deletions yazi-dds/src/body/bulk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ pub struct BodyBulkIter {
}

impl UserData for BodyBulkIter {
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("tab", |_, me| Ok(me.tab));
}

fn add_methods<'a, M: mlua::UserDataMethods<'a, Self>>(methods: &mut M) {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.inner.len()));

methods.add_meta_function(MetaMethod::Pairs, |lua, me: AnyUserData| {
Expand Down
6 changes: 3 additions & 3 deletions yazi-dds/src/body/tabs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub struct BodyTabsItem<'a> {
}

impl UserData for BodyTabsItem<'static> {
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("url", |lua, me| lua.create_any_userdata(me.url.clone()));
}
}
Expand All @@ -69,11 +69,11 @@ impl From<BodyTabs<'static>> for BodyTabsIter {
}

impl UserData for BodyTabsIter {
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("cursor", |_, me| Ok(me.cursor));
}

fn add_methods<'a, M: mlua::UserDataMethods<'a, Self>>(methods: &mut M) {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.items.len()));

methods.add_meta_method(MetaMethod::Index, |_, me, idx: usize| {
Expand Down
4 changes: 2 additions & 2 deletions yazi-dds/src/body/yank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ impl From<BodyYank<'static>> for BodyYankIter {
}

impl UserData for BodyYankIter {
fn add_fields<'a, F: mlua::UserDataFields<'a, Self>>(fields: &mut F) {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("is_cut", |_, me| Ok(me.cut));
}

fn add_methods<'a, M: mlua::UserDataMethods<'a, Self>>(methods: &mut M) {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.urls.len()));

methods.add_meta_method(MetaMethod::Index, |lua, me, idx: usize| {
Expand Down
9 changes: 6 additions & 3 deletions yazi-fm/src/app/commands/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt::Display;

use mlua::TableExt;
use tracing::warn;
use yazi_plugin::{OptData, LOADER, LUA};
use yazi_plugin::{loader::LOADER, OptData, RtRef, LUA};
use yazi_shared::{emit, event::Cmd, Defer, Layer};

use crate::{app::App, lives::Lives};
Expand Down Expand Up @@ -40,9 +40,12 @@ impl App {
Err(e) => return warn!("{e}"),
};

LOADER.set_running(Some(&opt.name));
let _defer = Defer::new(|| LOADER.set_running(None));
match LUA.named_registry_value::<RtRef>("rt") {
Ok(mut r) => r.swap(&opt.name),
Err(e) => return warn!("{e}"),
}

let _defer = Defer::new(|| LUA.named_registry_value::<RtRef>("rt").map(|mut r| r.reset()));
let plugin = match LOADER.load(&opt.name) {
Ok(plugin) => plugin,
Err(e) => return warn!("{e}"),
Expand Down
10 changes: 0 additions & 10 deletions yazi-plugin/preset/setup.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1 @@
package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path

local _require = require
require = function(name)
YAZI_PLUGIN_NAME, YAZI_SYNC_CALLS = name, 0
local mod = _require(name)
mod._name = name
return mod
end

YAZI_SYNC_BLOCKS = {}
13 changes: 0 additions & 13 deletions yazi-plugin/preset/ya.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,6 @@ function ya.flat(t)
return r
end

function ya.sync(f)
YAZI_SYNC_CALLS = YAZI_SYNC_CALLS + 1

local name, calls = YAZI_PLUGIN_NAME, YAZI_SYNC_CALLS
if not YAZI_SYNC_BLOCKS then
return function(...) return ya.plugin_retrieve(name, calls, ...) end
end

YAZI_SYNC_BLOCKS[name] = YAZI_SYNC_BLOCKS[name] or {}
YAZI_SYNC_BLOCKS[name][calls] = f
return function(...) return f(package.loaded[name], ...) end
end

function ya.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end

function ya.readable_size(size)
Expand Down
2 changes: 1 addition & 1 deletion yazi-plugin/src/isolate/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use tokio::runtime::Handle;
use yazi_dds::ValueSendable;

use super::slim_lua;
use crate::LOADER;
use crate::loader::LOADER;

pub async fn entry(name: String, args: Vec<ValueSendable>) -> mlua::Result<()> {
LOADER.ensure(&name).await.into_lua_err()?;
Expand Down
13 changes: 4 additions & 9 deletions yazi-plugin/src/isolate/isolate.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use mlua::Lua;

use crate::{bindings, elements};
use crate::{bindings, elements, runtime::Runtime};

pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
let lua = Lua::new();
lua.set_named_registry_value("rt", Runtime::new(name))?;

// Base
bindings::Cha::register(&lua)?;
Expand All @@ -12,7 +13,7 @@ pub fn slim_lua(name: &str) -> mlua::Result<Lua> {

crate::fs::install(&lua)?;
crate::process::install(&lua)?;
crate::utils::install(&lua)?;
crate::utils::install_isolate(&lua)?;
crate::Config::new(&lua).install_preview()?;
lua.load(include_str!("../../preset/ya.lua")).exec()?;

Expand All @@ -24,12 +25,6 @@ pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
elements::Rect::install(&lua, &ui)?;
elements::Span::install(&lua, &ui)?;

{
let globals = lua.globals();
globals.raw_set("ui", ui)?;
globals.raw_set("YAZI_PLUGIN_NAME", lua.create_string(name)?)?;
globals.raw_set("YAZI_SYNC_CALLS", 0)?;
}

lua.globals().raw_set("ui", ui)?;
Ok(lua)
}
2 changes: 1 addition & 1 deletion yazi-plugin/src/isolate/peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use yazi_config::LAYOUT;
use yazi_shared::{emit, event::Cmd, Layer};

use super::slim_lua;
use crate::{bindings::{Cast, File, Window}, elements::Rect, OptData, LOADER, LUA};
use crate::{bindings::{Cast, File, Window}, elements::Rect, loader::LOADER, OptData, LUA};

pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> CancellationToken {
let ct = CancellationToken::new();
Expand Down
2 changes: 1 addition & 1 deletion yazi-plugin/src/isolate/preload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use tokio::runtime::Handle;
use yazi_config::LAYOUT;

use super::slim_lua;
use crate::{bindings::{Cast, File}, elements::Rect, LOADER};
use crate::{bindings::{Cast, File}, elements::Rect, loader::LOADER};

pub async fn preload(
name: &str,
Expand Down
10 changes: 7 additions & 3 deletions yazi-plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@ pub mod elements;
pub mod external;
pub mod fs;
pub mod isolate;
mod loader;
pub mod loader;
mod lua;
mod opt;
pub mod process;
pub mod pubsub;
mod runtime;
pub mod url;
pub mod utils;

pub use cast::*;
pub use config::*;
pub use loader::*;
pub use lua::*;
pub use opt::*;
pub use runtime::*;

pub fn init() { crate::init_lua(); }
pub fn init() {
crate::init_lua();
crate::loader::init();
}
40 changes: 11 additions & 29 deletions yazi-plugin/src/loader.rs → yazi-plugin/src/loader/loader.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{borrow::Cow, collections::HashMap, ops::Deref, sync::Arc};
use std::{borrow::Cow, collections::HashMap, ops::Deref};

use anyhow::{bail, Result};
use mlua::{ExternalError, Table};
Expand All @@ -11,20 +11,12 @@ use crate::LUA;

pub static LOADER: RoCell<Loader> = RoCell::new();

pub(super) static RUNNING: RoCell<arc_swap::ArcSwapOption<String>> = RoCell::new();

#[derive(Default)]
pub struct Loader {
cache: RwLock<HashMap<String, Vec<u8>>>,
}

impl Loader {
#[inline]
pub(super) fn init() {
LOADER.with(Default::default);
RUNNING.with(Default::default);
}

pub async fn ensure(&self, name: &str) -> Result<()> {
if self.cache.read().contains_key(name) {
return Ok(());
Expand All @@ -33,16 +25,16 @@ impl Loader {
let path = BOOT.plugin_dir.join(format!("{name}.yazi/init.lua"));
let b = fs::read(path).await.map(|v| v.into()).or_else(|_| {
Ok(Cow::from(match name {
"archive" => include_bytes!("../preset/plugins/archive.lua") as &[u8],
"code" => include_bytes!("../preset/plugins/code.lua"),
"file" => include_bytes!("../preset/plugins/file.lua"),
"folder" => include_bytes!("../preset/plugins/folder.lua"),
"image" => include_bytes!("../preset/plugins/image.lua"),
"json" => include_bytes!("../preset/plugins/json.lua"),
"mime" => include_bytes!("../preset/plugins/mime.lua"),
"noop" => include_bytes!("../preset/plugins/noop.lua"),
"pdf" => include_bytes!("../preset/plugins/pdf.lua"),
"video" => include_bytes!("../preset/plugins/video.lua"),
"archive" => include_bytes!("../../preset/plugins/archive.lua") as &[_],
"code" => include_bytes!("../../preset/plugins/code.lua"),
"file" => include_bytes!("../../preset/plugins/file.lua"),
"folder" => include_bytes!("../../preset/plugins/folder.lua"),
"image" => include_bytes!("../../preset/plugins/image.lua"),
"json" => include_bytes!("../../preset/plugins/json.lua"),
"mime" => include_bytes!("../../preset/plugins/mime.lua"),
"noop" => include_bytes!("../../preset/plugins/noop.lua"),
"pdf" => include_bytes!("../../preset/plugins/pdf.lua"),
"video" => include_bytes!("../../preset/plugins/video.lua"),
_ => bail!("plugin not found: {name}"),
}))
})?;
Expand All @@ -58,8 +50,6 @@ impl Loader {
return Ok(t);
}

globals.raw_set("YAZI_PLUGIN_NAME", LUA.create_string(name)?)?;
globals.raw_set("YAZI_SYNC_CALLS", 0)?;
let t: Table = match self.read().get(name) {
Some(b) => LUA.load(b).call(())?,
None => Err(format!("plugin `{name}` not found").into_lua_err())?,
Expand All @@ -69,14 +59,6 @@ impl Loader {
loaded.raw_set(name, t.clone())?;
Ok(t)
}

pub fn set_running(&self, name: Option<&str>) {
if let Some(s) = name {
RUNNING.store(Some(Arc::new(s.to_owned())));
} else {
RUNNING.store(None);
}
}
}

impl Deref for Loader {
Expand Down
15 changes: 15 additions & 0 deletions yazi-plugin/src/loader/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#![allow(clippy::module_inception)]

mod loader;
mod require;

pub use loader::*;
use require::*;

pub(super) fn init() { LOADER.with(Default::default); }

pub(super) fn install(lua: &'static mlua::Lua) -> mlua::Result<()> {
Require::install(lua)?;

Ok(())
}
66 changes: 66 additions & 0 deletions yazi-plugin/src/loader/require.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use mlua::{ExternalResult, Function, IntoLua, Lua, MetaMethod, Table, TableExt, UserData, Value, Variadic};

use crate::RtRef;

pub(super) struct Require;

impl Require {
pub(super) fn install(lua: &'static Lua) -> mlua::Result<()> {
let globals = lua.globals();

let require = globals.raw_get::<_, Function>("require")?;
globals.raw_set(
"require",
lua.create_function(move |lua, name: mlua::String| {
lua.named_registry_value::<RtRef>("rt")?.swap(name.to_str()?);
let module: Table = require.call(&name)?;
lua.named_registry_value::<RtRef>("rt")?.reset();

module.raw_set("_name", &name)?;
Self::create_mt(lua, name, module)
})?,
)?;

Ok(())
}

fn create_mt(
lua: &'static Lua,
name: mlua::String<'static>,
module: Table<'static>,
) -> mlua::Result<Table<'static>> {
let ts =
lua.create_table_from([("name", name.into_lua(lua)?), ("module", module.into_lua(lua)?)])?;

let mt = lua.create_table()?;
mt.raw_set(
"__index",
lua.create_function(|_, (ts, key): (Table, mlua::String)| {
if key.to_str()? == "setup" {
Ok(RequireSetup { name: ts.raw_get("name")?, module: ts.raw_get("module")? })
} else {
Err("Only `require():setup()` is supported").into_lua_err()
}
})?,
)?;

ts.set_metatable(Some(mt));
Ok(ts)
}
}

pub(super) struct RequireSetup {
name: mlua::String<'static>,
module: Table<'static>,
}

impl UserData for RequireSetup {
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Call, |lua, me, args: Variadic<Value>| {
lua.named_registry_value::<RtRef>("rt")?.swap(me.name.to_str()?);
let result = me.module.call_method::<_, Variadic<Value>>("setup", args);
lua.named_registry_value::<RtRef>("rt")?.reset();
result
});
}
}
Loading

0 comments on commit c240602

Please sign in to comment.