perf: app data instead of Lua registry to reduce stack pushes (#2880)

This commit is contained in:
三咲雅 misaki masa 2025-06-16 11:25:02 +08:00 committed by GitHub
parent 51560c30b7
commit 52d37fa25d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 44 additions and 33 deletions

View file

@ -1,7 +1,7 @@
use mlua::IntoLua;
use tracing::error;
use yazi_dds::{LOCAL, Payload, REMOTE};
use yazi_plugin::{LUA, RtRefMut};
use yazi_plugin::{LUA, runtime_mut};
use yazi_shared::event::CmdCow;
use crate::{app::App, lives::Lives};
@ -27,11 +27,11 @@ impl App {
_ = Lives::scope(&self.cx, || {
let body = payload.body.into_lua(&LUA)?;
for (id, cb) in handlers {
LUA.named_registry_value::<RtRefMut>("ir")?.push(&id);
runtime_mut!(LUA)?.push(&id);
if let Err(e) = cb.call::<()>(body.clone()) {
error!("Failed to run `{kind}` event handler in your `{id}` plugin: {e}");
}
LUA.named_registry_value::<RtRefMut>("ir")?.pop();
runtime_mut!(LUA)?.pop();
}
Ok(())
});

View file

@ -4,7 +4,7 @@ use mlua::ObjectLike;
use scopeguard::defer;
use tracing::{error, warn};
use yazi_dds::Sendable;
use yazi_plugin::{LUA, RtRefMut, loader::{LOADER, Loader}};
use yazi_plugin::{LUA, loader::{LOADER, Loader}, runtime_mut};
use yazi_proxy::{AppProxy, options::{PluginMode, PluginOpt}};
use crate::{app::App, lives::Lives};
@ -55,11 +55,11 @@ impl App {
return self.cx.tasks.plugin_micro(opt);
}
match LUA.named_registry_value::<RtRefMut>("ir") {
match runtime_mut!(LUA) {
Ok(mut r) => r.push(&opt.id),
Err(e) => return warn!("{e}"),
}
defer! { _ = LUA.named_registry_value::<RtRefMut>("ir").map(|mut r| r.pop()) }
defer! { _ = runtime_mut!(LUA).map(|mut r| r.pop()) }
let plugin = match LOADER.load_with(&LUA, &opt.id, chunk) {
Ok(t) => t,

View file

@ -5,7 +5,7 @@ use crate::runtime::Runtime;
pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
let lua = Lua::new();
lua.set_named_registry_value("ir", Runtime::new(name))?;
lua.set_app_data(Runtime::new(name));
// Base
let globals = lua.globals();

View file

@ -3,7 +3,7 @@ use std::sync::Arc;
use mlua::{ExternalResult, Function, IntoLua, Lua, MetaMethod, MultiValue, ObjectLike, Table, Value};
use super::LOADER;
use crate::RtRefMut;
use crate::runtime_mut;
pub(super) struct Require;
@ -15,9 +15,9 @@ impl Require {
let s = &id.to_str()?;
futures::executor::block_on(LOADER.ensure(s, |_| ())).into_lua_err()?;
lua.named_registry_value::<RtRefMut>("ir")?.push(s);
runtime_mut!(lua)?.push(s);
let mod_ = LOADER.load(lua, s);
lua.named_registry_value::<RtRefMut>("ir")?.pop();
runtime_mut!(lua)?.pop();
Self::create_mt(lua, s, mod_?, true)
})?,
@ -31,9 +31,9 @@ impl Require {
let s = &id.to_str()?;
LOADER.ensure(s, |_| ()).await.into_lua_err()?;
lua.named_registry_value::<RtRefMut>("ir")?.push(s);
runtime_mut!(lua)?.push(s);
let mod_ = LOADER.load(&lua, s);
lua.named_registry_value::<RtRefMut>("ir")?.pop();
runtime_mut!(lua)?.pop();
Self::create_mt(&lua, s, mod_?, false)
})?,
@ -73,9 +73,9 @@ impl Require {
if sync {
lua.create_function(move |lua, args: MultiValue| {
let (r#mod, args) = Self::split_mod_and_args(lua, &id, args)?;
lua.named_registry_value::<RtRefMut>("ir")?.push(&id);
runtime_mut!(lua)?.push(&id);
let result = r#mod.call_function::<MultiValue>(&f, args);
lua.named_registry_value::<RtRefMut>("ir")?.pop();
runtime_mut!(lua)?.pop();
result
})
} else {
@ -83,9 +83,9 @@ impl Require {
let (id, f) = (id.clone(), f.clone());
async move {
let (r#mod, args) = Self::split_mod_and_args(&lua, &id, args)?;
lua.named_registry_value::<RtRefMut>("ir")?.push(&id);
runtime_mut!(lua)?.push(&id);
let result = r#mod.call_async_function::<MultiValue>(&f, args).await;
lua.named_registry_value::<RtRefMut>("ir")?.pop();
runtime_mut!(lua)?.pop();
result
}
})

View file

@ -17,7 +17,7 @@ pub(super) fn init_lua() -> Result<()> {
}
fn stage_1(lua: &'static Lua) -> Result<()> {
lua.set_named_registry_value("ir", Runtime::default())?;
lua.set_app_data(Runtime::default());
// Base
let globals = lua.globals();

View file

@ -120,6 +120,22 @@ macro_rules! impl_file_methods {
};
}
#[macro_export]
macro_rules! runtime {
($lua:ident) => {{
use mlua::ExternalError;
$lua.app_data_ref::<$crate::Runtime>().ok_or_else(|| "Runtime not found".into_lua_err())
}};
}
#[macro_export]
macro_rules! runtime_mut {
($lua:ident) => {{
use mlua::ExternalError;
$lua.app_data_mut::<$crate::Runtime>().ok_or_else(|| "Runtime not found".into_lua_err())
}};
}
#[macro_export]
macro_rules! deprecate {
($lua:ident, $tt:tt) => {{

View file

@ -2,7 +2,7 @@ use mlua::{ExternalResult, Function, Lua, Value};
use yazi_binding::Id;
use yazi_dds::body::Body;
use crate::runtime::RtRef;
use crate::runtime;
pub struct Pubsub;
@ -23,7 +23,7 @@ impl Pubsub {
pub(super) fn sub(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
let rt = lua.named_registry_value::<RtRef>("ir")?;
let rt = runtime!(lua)?;
let Some(cur) = rt.current() else {
return Err("`sub()` must be called in a sync plugin").into_lua_err();
};
@ -36,7 +36,7 @@ impl Pubsub {
pub(super) fn sub_remote(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|lua, (kind, f): (mlua::String, Function)| {
let rt = lua.named_registry_value::<RtRef>("ir")?;
let rt = runtime!(lua)?;
let Some(cur) = rt.current() else {
return Err("`sub_remote()` must be called in a sync plugin").into_lua_err();
};
@ -49,7 +49,7 @@ impl Pubsub {
pub(super) fn unsub(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|lua, kind: mlua::String| {
if let Some(cur) = lua.named_registry_value::<RtRef>("ir")?.current() {
if let Some(cur) = runtime!(lua)?.current() {
Ok(yazi_dds::Pubsub::unsub(cur, &kind.to_str()?))
} else {
Err("`unsub()` must be called in a sync plugin").into_lua_err()
@ -59,7 +59,7 @@ impl Pubsub {
pub(super) fn unsub_remote(lua: &Lua) -> mlua::Result<Function> {
lua.create_function(|lua, kind: mlua::String| {
if let Some(cur) = lua.named_registry_value::<RtRef>("ir")?.current() {
if let Some(cur) = runtime!(lua)?.current() {
Ok(yazi_dds::Pubsub::unsub_remote(cur, &kind.to_str()?))
} else {
Err("`unsub_remote()` must be called in a sync plugin").into_lua_err()

View file

@ -1,6 +1,6 @@
use std::collections::{HashMap, VecDeque};
use mlua::{Function, UserData};
use mlua::Function;
#[derive(Debug, Default)]
pub struct Runtime {
@ -14,9 +14,6 @@ struct RuntimeFrame {
calls: usize,
}
pub type RtRef = mlua::UserDataRef<Runtime>;
pub type RtRefMut = mlua::UserDataRefMut<Runtime>;
impl Runtime {
pub fn new(id: &str) -> Self {
Self {
@ -56,5 +53,3 @@ impl Runtime {
true
}
}
impl UserData for Runtime {}

View file

@ -6,18 +6,18 @@ use yazi_proxy::{AppProxy, options::{PluginCallback, PluginOpt}};
use yazi_shared::event::Data;
use super::Utils;
use crate::{RtRefMut, bindings::{MpscRx, MpscTx, MpscUnboundedRx, MpscUnboundedTx, OneshotRx, OneshotTx}, loader::LOADER, runtime::RtRef};
use crate::{bindings::{MpscRx, MpscTx, MpscUnboundedRx, MpscUnboundedTx, OneshotRx, OneshotTx}, loader::LOADER, runtime, runtime_mut};
impl Utils {
pub(super) fn sync(lua: &Lua, isolate: bool) -> mlua::Result<Function> {
if isolate {
lua.create_function(|lua, ()| {
let Some(block) = lua.named_registry_value::<RtRefMut>("ir")?.next_block() else {
let Some(block) = runtime_mut!(lua)?.next_block() else {
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
};
lua.create_async_function(move |lua, args: MultiValue| async move {
let Some(cur) = lua.named_registry_value::<RtRef>("ir")?.current_owned() else {
let Some(cur) = runtime!(lua)?.current_owned() else {
return Err("block spawned by `ya.sync()` must be called in a plugin").into_lua_err();
};
Sendable::list_to_values(&lua, Self::retrieve(cur, block, args).await?)
@ -25,7 +25,7 @@ impl Utils {
})
} else {
lua.create_function(|lua, f: Function| {
let mut rt = lua.named_registry_value::<RtRefMut>("ir")?;
let mut rt = runtime_mut!(lua)?;
if !rt.put_block(f.clone()) {
return Err("`ya.sync()` must be called in a plugin").into_lua_err();
}
@ -84,7 +84,7 @@ impl Utils {
let callback: PluginCallback = {
let id = id.clone();
Box::new(move |lua, plugin| {
let Some(block) = lua.named_registry_value::<RtRef>("ir")?.get_block(&id, calls) else {
let Some(block) = runtime!(lua)?.get_block(&id, calls) else {
return Err("sync block not found".into_lua_err());
};