Skip to content

Commit

Permalink
Fix Lua API performance by caching
Browse files Browse the repository at this point in the history
Fixes: #412
  • Loading branch information
sayanarijit committed Nov 15, 2021
1 parent 132b528 commit 0bc2a0f
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 38 deletions.
25 changes: 25 additions & 0 deletions src/__cache__.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-- Please ignore me and move on.
-- Or if you insist, see https://github.com/sayanarijit/xplr/issues/412

local xplr = xplr

xplr.__CACHE__ = { directory_nodes = {} }

function xplr.__CACHE__.set_directory_nodes(nodes)
xplr.__CACHE__.directory_nodes = nodes
end

function xplr.__CACHE__.call(fun, arg)
if arg.app and arg.app.directory_buffer then
arg.app.directory_buffer.nodes = xplr.__CACHE__.directory_nodes
elseif arg.directory_buffer then
arg.directory_buffer.nodes = xplr.__CACHE__.directory_nodes
end
return fun(arg)
end

function xplr.__CACHE__.caller(fun)
return function(arg)
return xplr.__CACHE__.call(fun, arg)
end
end
29 changes: 26 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@ pub struct Command {

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum MsgOut {
CacheDirectoryNodes(Vec<Node>),
ExplorePwdAsync,
ExploreParentsAsync,
Refresh,
Expand Down Expand Up @@ -1246,12 +1247,29 @@ impl History {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct CachedDirectoryBuffer {
pub parent: String,
pub total: usize,
pub focus: usize,
}

impl CachedDirectoryBuffer {
pub fn new(buf: &DirectoryBuffer) -> Self {
Self {
parent: buf.parent.clone(),
total: buf.total,
focus: buf.focus,
}
}
}

#[derive(Debug, Clone, Serialize)]
pub struct CallLuaArg {
pub version: String,
pub pwd: String,
pub focused_node: Option<Node>,
pub directory_buffer: Option<DirectoryBuffer>,
pub directory_buffer: Option<CachedDirectoryBuffer>,
pub selection: IndexSet<Node>,
pub mode: Mode,
pub layout: Layout,
Expand Down Expand Up @@ -2246,6 +2264,8 @@ impl App {
dir.focused_node().map(|n| n.relative_path.clone()),
)?;
if dir.parent == self.pwd {
self.msg_out
.push_back(MsgOut::CacheDirectoryNodes(dir.nodes.clone()));
self.directory_buffer = Some(dir);
}
Ok(self)
Expand Down Expand Up @@ -2741,7 +2761,10 @@ impl App {
version: self.version.clone(),
pwd: self.pwd.clone(),
focused_node: self.focused_node().cloned(),
directory_buffer: self.directory_buffer.clone(),
directory_buffer: self
.directory_buffer
.as_ref()
.map(|buf| CachedDirectoryBuffer::new(buf)),
selection: self.selection.clone(),
mode: self.mode.clone(),
layout: self.layout.clone(),
Expand Down
45 changes: 18 additions & 27 deletions src/lua.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::app::Node;
use crate::app::VERSION;
use crate::config::Config;
use anyhow::bail;
Expand All @@ -8,6 +9,7 @@ use serde::Deserialize;
use std::fs;

const DEFAULT_LUA_SCRIPT: &str = include_str!("init.lua");
const INTERNAL_LUA_SCRIPT: &str = include_str!("__cache__.lua");
const UPGRADE_GUIDE_LINK: &str = "https://xplr.dev/en/upgrade-guide.html";

fn parse_version(version: &str) -> Result<(u16, u16, u16, Option<u16>)> {
Expand Down Expand Up @@ -49,30 +51,6 @@ pub fn check_version(version: &str, path: &str) -> Result<()> {
}
}

fn resolve_fn_recursive<'lua, 'a>(
table: &mlua::Table<'lua>,
mut path: impl Iterator<Item = &'a str>,
) -> Result<mlua::Function<'lua>> {
if let Some(nxt) = path.next() {
match table.get(nxt)? {
mlua::Value::Table(t) => resolve_fn_recursive(&t, path),
mlua::Value::Function(f) => Ok(f),
t => bail!("{:?} is not a function", t),
}
} else {
bail!("Invalid path")
}
}

/// This function resolves paths like `builtin.func_foo`, `custom.func_bar` into lua functions.
pub fn resolve_fn<'lua>(
globals: &mlua::Table<'lua>,
path: &str,
) -> Result<mlua::Function<'lua>> {
let path = format!("xplr.fn.{}", path);
resolve_fn_recursive(globals, path.split('.'))
}

/// Used to initialize Lua globals
pub fn init(lua: &Lua) -> Result<Config> {
let config = Config::default();
Expand All @@ -91,6 +69,7 @@ pub fn init(lua: &Lua) -> Result<Config> {
globals.set("xplr", lua_xplr)?;

lua.load(DEFAULT_LUA_SCRIPT).set_name("init")?.exec()?;
lua.load(INTERNAL_LUA_SCRIPT).set_name("internal")?.exec()?;

let lua_xplr: mlua::Table = globals.get("xplr")?;
let config: Config = lua.from_value(lua_xplr.get("config")?)?;
Expand Down Expand Up @@ -123,14 +102,26 @@ pub fn extend(lua: &Lua, path: &str) -> Result<Config> {
pub fn call<'lua, R: Deserialize<'lua>>(
lua: &'lua Lua,
func: &str,
args: mlua::Value<'lua>,
arg: mlua::Value<'lua>,
) -> Result<R> {
let func = resolve_fn(&lua.globals(), func)?;
let res: mlua::Value = func.call(args)?;
let func = format!("xplr.__CACHE__.caller(xplr.fn.{})", func);
let caller: mlua::Function = lua.load(&func).eval()?;
let res: mlua::Value = caller.call(arg)?;
let res: R = lua.from_value(res)?;
Ok(res)
}

/// Used to cache the directory nodes.
pub fn cache_directory_nodes<'lua>(
lua: &'lua Lua,
nodes: &[Node],
) -> Result<()> {
let func = "xplr.__CACHE__.set_directory_nodes";
let func: mlua::Function = lua.load(func).eval()?;
func.call(lua.to_value(nodes)?)?;
Ok(())
}

#[cfg(test)]
mod tests {

Expand Down
11 changes: 4 additions & 7 deletions src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,6 @@ fn call_lua(
func: &str,
_silent: bool,
) -> Result<Option<Vec<app::ExternalMsg>>> {
let _focus_index = app
.directory_buffer
.as_ref()
.map(|d| d.focus)
.unwrap_or_default()
.to_string();

let arg = app.to_lua_arg();
let arg = lua.to_value(&arg)?;
lua::call(lua, func, arg)
Expand Down Expand Up @@ -280,6 +273,10 @@ impl Runner {
tx_msg_in.send(task)?;
}

CacheDirectoryNodes(nodes) => {
lua::cache_directory_nodes(&lua, &nodes)?;
}

Quit => {
result = Ok(None);
break 'outer;
Expand Down
2 changes: 1 addition & 1 deletion src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1203,7 +1203,7 @@ impl From<TuiRect> for Rect {
}
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize)]
pub struct ContentRendererArg {
app: app::CallLuaArg,
screen_size: Rect,
Expand Down

0 comments on commit 0bc2a0f

Please sign in to comment.