mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
perf: cache loaded plugins (#710)
This commit is contained in:
parent
17f946dcdb
commit
d954784643
10 changed files with 79 additions and 83 deletions
|
|
@ -1,8 +1,8 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use mlua::{ExternalError, Table, TableExt};
|
||||
use mlua::TableExt;
|
||||
use tracing::warn;
|
||||
use yazi_plugin::{LOADED, LUA};
|
||||
use yazi_plugin::{OptData, LOADED, LUA};
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
use crate::{app::App, lives::Lives};
|
||||
|
|
@ -24,32 +24,28 @@ impl App {
|
|||
|
||||
tokio::spawn(async move {
|
||||
if LOADED.ensure(&opt.name).await.is_ok() {
|
||||
emit!(Call(Cmd::args("plugin_do", vec![opt.name]).with_data(opt.data), Layer::App));
|
||||
Self::_plugin_do(opt.name, opt.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn _plugin_do(name: String, data: OptData) {
|
||||
emit!(Call(Cmd::args("plugin_do", vec![name]).with_data(data), Layer::App));
|
||||
}
|
||||
|
||||
pub(crate) fn plugin_do(&mut self, opt: impl TryInto<yazi_plugin::Opt, Error = impl Display>) {
|
||||
let opt = match opt.try_into() {
|
||||
Ok(opt) => opt as yazi_plugin::Opt,
|
||||
Err(e) => return warn!("{e}"),
|
||||
};
|
||||
|
||||
let plugin = match LOADED.load(&opt.name) {
|
||||
Ok(plugin) => plugin,
|
||||
Err(e) => return warn!("{e}"),
|
||||
};
|
||||
|
||||
_ = Lives::scope(&self.cx, |_| {
|
||||
if let Some(init) = opt.data.init {
|
||||
init(&LUA)?;
|
||||
}
|
||||
LUA.globals().set("YAZI_PLUGIN_NAME", LUA.create_string(&opt.name)?)?;
|
||||
|
||||
let mut plugin: Option<Table> = None;
|
||||
if let Some(b) = LOADED.read().get(&opt.name) {
|
||||
plugin = LUA.load(b).call(())?;
|
||||
}
|
||||
|
||||
let Some(plugin) = plugin else {
|
||||
return Err("plugin not found".into_lua_err());
|
||||
};
|
||||
|
||||
if let Some(cb) = opt.data.cb {
|
||||
cb(&LUA, plugin)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ impl Lives {
|
|||
SCOPE.init(unsafe { mem::transmute(scope) });
|
||||
LUA.set_named_registry_value("cx", scope.create_any_userdata_ref(cx)?)?;
|
||||
|
||||
let global = LUA.globals();
|
||||
global.set(
|
||||
let globals = LUA.globals();
|
||||
globals.set(
|
||||
"cx",
|
||||
LUA.create_table_from([
|
||||
("active", super::Tab::make(cx.manager.active())?),
|
||||
|
|
@ -51,11 +51,11 @@ impl Lives {
|
|||
let ret = f(scope)?;
|
||||
|
||||
LAYOUT.store(Arc::new(yazi_config::Layout {
|
||||
header: *global.raw_get::<_, Table>("Header")?.raw_get::<_, RectRef>("area")?,
|
||||
parent: *global.raw_get::<_, Table>("Parent")?.raw_get::<_, RectRef>("area")?,
|
||||
current: *global.raw_get::<_, Table>("Current")?.raw_get::<_, RectRef>("area")?,
|
||||
preview: *global.raw_get::<_, Table>("Preview")?.raw_get::<_, RectRef>("area")?,
|
||||
status: *global.raw_get::<_, Table>("Status")?.raw_get::<_, RectRef>("area")?,
|
||||
header: *globals.raw_get::<_, Table>("Header")?.raw_get::<_, RectRef>("area")?,
|
||||
parent: *globals.raw_get::<_, Table>("Parent")?.raw_get::<_, RectRef>("area")?,
|
||||
current: *globals.raw_get::<_, Table>("Current")?.raw_get::<_, RectRef>("area")?,
|
||||
preview: *globals.raw_get::<_, Table>("Preview")?.raw_get::<_, RectRef>("area")?,
|
||||
status: *globals.raw_get::<_, Table>("Status")?.raw_get::<_, RectRef>("area")?,
|
||||
}));
|
||||
|
||||
SCOPE.drop();
|
||||
|
|
|
|||
9
yazi-plugin/preset/setup.lua
Normal file
9
yazi-plugin/preset/setup.lua
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path
|
||||
|
||||
local _require = require
|
||||
require = function(name)
|
||||
YAZI_PLUGIN_NAME, YAZI_SYNC_CALLS = name, 0
|
||||
return _require(name)
|
||||
end
|
||||
|
||||
YAZI_SYNC_BLOCKS = {}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
local cache = {}
|
||||
local sub_mt = {
|
||||
__index = function(target, k)
|
||||
local bucket = rawget(target, "__yazi_bucket")
|
||||
return cache[bucket] and cache[bucket][k]
|
||||
end,
|
||||
__newindex = function(target, k, v)
|
||||
local bucket = rawget(target, "__yazi_bucket")
|
||||
cache[bucket] = cache[bucket] or {}
|
||||
cache[bucket][k] = v
|
||||
end,
|
||||
}
|
||||
|
||||
state = setmetatable({}, {
|
||||
__index = function(_, k)
|
||||
local bucket = YAZI_PLUGIN_NAME
|
||||
return cache[bucket] and cache[bucket][k]
|
||||
end,
|
||||
__newindex = function(_, k, v)
|
||||
local bucket = YAZI_PLUGIN_NAME
|
||||
cache[bucket] = cache[bucket] or {}
|
||||
cache[bucket][k] = v
|
||||
end,
|
||||
__call = function(_, name) return setmetatable({ __yazi_bucket = name or YAZI_PLUGIN_NAME }, sub_mt) end,
|
||||
})
|
||||
|
|
@ -29,17 +29,16 @@ function ya.flat(t)
|
|||
end
|
||||
|
||||
function ya.sync(f)
|
||||
if ya.SYNC_ON then
|
||||
return function(...) f(...) end
|
||||
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 = YAZI_SYNC_BLOCKS + 1
|
||||
if YAZI_SYNC_CALLS == YAZI_SYNC_BLOCKS then
|
||||
YAZI_SYNC_ENTRY = f
|
||||
end
|
||||
|
||||
local blocks = YAZI_SYNC_BLOCKS
|
||||
return function(...) return ya.plugin_retrieve(YAZI_PLUGIN_NAME, blocks, ...) 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
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub async fn entry(name: String, args: Vec<ValueSendable>) -> mlua::Result<()> {
|
|||
let globals = lua.globals();
|
||||
|
||||
globals.raw_set("YAZI_PLUGIN_NAME", lua.create_string(&name)?)?;
|
||||
globals.raw_set("YAZI_SYNC_BLOCKS", 0)?;
|
||||
globals.raw_set("YAZI_SYNC_CALLS", 0)?;
|
||||
|
||||
let plugin: Table = if let Some(b) = LOADED.read().get(&name) {
|
||||
lua.load(b).call(())?
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
use std::{borrow::Cow, collections::BTreeMap, ops::Deref};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use mlua::{ExternalError, Table};
|
||||
use parking_lot::RwLock;
|
||||
use tokio::fs;
|
||||
use yazi_config::BOOT;
|
||||
use yazi_shared::RoCell;
|
||||
|
||||
use crate::LUA;
|
||||
|
||||
pub static LOADED: RoCell<Loader> = RoCell::new();
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -42,6 +45,24 @@ impl Loader {
|
|||
self.loaded.write().insert(name.to_owned(), b.into_owned());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load(&self, name: &str) -> mlua::Result<Table> {
|
||||
let globals = LUA.globals();
|
||||
let loaded: Table = globals.raw_get::<_, Table>("package")?.raw_get("loaded")?;
|
||||
if let Ok(t) = loaded.raw_get::<_, Table>(name) {
|
||||
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())?,
|
||||
};
|
||||
|
||||
loaded.raw_set(name, t.clone())?;
|
||||
Ok(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Loader {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ pub struct Opt {
|
|||
#[derive(Default)]
|
||||
pub struct OptData {
|
||||
pub args: Vec<ValueSendable>,
|
||||
pub init: Option<Box<dyn FnOnce(&Lua) -> mlua::Result<()> + Send>>,
|
||||
pub cb: Option<Box<dyn FnOnce(&Lua, Table) -> mlua::Result<()> + Send>>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ pub fn init() {
|
|||
|
||||
// Base
|
||||
lua.load(include_str!("../preset/inspect/inspect.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/state.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/ya.lua")).exec()?;
|
||||
crate::bindings::Cha::register(lua)?;
|
||||
crate::bindings::File::register(lua)?;
|
||||
|
|
@ -36,11 +35,7 @@ pub fn init() {
|
|||
}
|
||||
|
||||
fn stage_2(lua: &Lua) {
|
||||
let setup = br#"
|
||||
ya.SYNC_ON = true
|
||||
package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path
|
||||
"#;
|
||||
lua.load(setup as &[u8]).exec().unwrap();
|
||||
lua.load(include_str!("../preset/setup.lua")).exec().unwrap();
|
||||
|
||||
if let Ok(b) = std::fs::read(BOOT.config_dir.join("init.lua")) {
|
||||
lua.load(b).exec().unwrap();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use mlua::{ExternalError, Function, Lua, Table, Value, Variadic};
|
||||
use mlua::{ExternalError, Function, IntoLua, Lua, Table, Value, Variadic};
|
||||
use tokio::sync::oneshot;
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
|
|
@ -10,31 +10,33 @@ impl Utils {
|
|||
ya.set(
|
||||
"plugin_retrieve",
|
||||
lua.create_async_function(
|
||||
|_, (name, blocks, args): (String, usize, Variadic<Value>)| async move {
|
||||
let args = Variadic::from_iter(ValueSendable::try_from_variadic(args)?);
|
||||
|_, (name, calls, args): (String, usize, Variadic<Value>)| async move {
|
||||
let args = ValueSendable::try_from_variadic(args)?;
|
||||
let (tx, rx) = oneshot::channel::<ValueSendable>();
|
||||
|
||||
let data = OptData {
|
||||
init: Some(Box::new(move |lua| {
|
||||
let globals = lua.globals();
|
||||
globals.raw_set("YAZI_SYNC_BLOCKS", 0)?;
|
||||
globals.raw_set("YAZI_SYNC_CALLS", blocks)?;
|
||||
Ok(())
|
||||
})),
|
||||
cb: Some(Box::new(move |lua, _| {
|
||||
let globals = lua.globals();
|
||||
cb: Some({
|
||||
let name = name.clone();
|
||||
Box::new(move |lua, plugin| {
|
||||
let blocks = lua.globals().raw_get::<_, Table>("YAZI_SYNC_BLOCKS")?;
|
||||
let block = blocks.raw_get::<_, Table>(name)?.raw_get::<_, Function>(calls)?;
|
||||
|
||||
let entry = globals.raw_get::<_, Function>("YAZI_SYNC_ENTRY")?;
|
||||
globals.raw_set("YAZI_SYNC_ENTRY", Value::Nil)?;
|
||||
let mut self_args = Vec::with_capacity(args.len() + 1);
|
||||
self_args.push(Value::Table(plugin));
|
||||
for arg in args {
|
||||
self_args.push(arg.into_lua(lua)?);
|
||||
}
|
||||
|
||||
let value: ValueSendable = entry.call::<_, Value>(args)?.try_into()?;
|
||||
tx.send(value).map_err(|_| "send failed".into_lua_err())
|
||||
})),
|
||||
let value: ValueSendable =
|
||||
block.call::<_, Value>(Variadic::from_iter(self_args))?.try_into()?;
|
||||
tx.send(value).map_err(|_| "send failed".into_lua_err())
|
||||
})
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
emit!(Call(
|
||||
Cmd::args("plugin", vec![name.to_owned()]).with_bool("sync", true).with_data(data),
|
||||
Cmd::args("plugin", vec![name.clone()]).with_bool("sync", true).with_data(data),
|
||||
Layer::App
|
||||
));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue