mirror of https://github.com/folke/lazy.nvim.git
perf(cache): cache loadfile and no find modpaths without package.loaders
This commit is contained in:
parent
32f2b71ff8
commit
faac2dd11c
|
@ -26,11 +26,12 @@ local cache_hash
|
||||||
---@alias CacheEntry {hash:CacheHash, modpath:string, chunk:string, used:number}
|
---@alias CacheEntry {hash:CacheHash, modpath:string, chunk:string, used:number}
|
||||||
---@type table<string,CacheEntry?>
|
---@type table<string,CacheEntry?>
|
||||||
M.cache = {}
|
M.cache = {}
|
||||||
M.loader_idx = 2 -- 2 so preload still works
|
|
||||||
M.enabled = true
|
M.enabled = true
|
||||||
M.ttl = 3600 * 24 * 5 -- keep unused modules for up to 5 days
|
M.ttl = 3600 * 24 * 5 -- keep unused modules for up to 5 days
|
||||||
---@type string[]
|
---@type string[]
|
||||||
M.rtp = nil
|
M.rtp = nil
|
||||||
|
-- selene:allow(global_usage)
|
||||||
|
M._loadfile = _G.loadfile
|
||||||
|
|
||||||
-- checks wether the cached modpath is still valid
|
-- checks wether the cached modpath is still valid
|
||||||
function M.check_path(modname, modpath)
|
function M.check_path(modname, modpath)
|
||||||
|
@ -65,9 +66,14 @@ function M.disable()
|
||||||
if not M.enabled then
|
if not M.enabled then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local idx = M.idx()
|
-- selene:allow(global_usage)
|
||||||
if idx then
|
_G.loadfile = M._loadfile
|
||||||
table.remove(package.loaders, idx)
|
---@diagnostic disable-next-line: no-unknown
|
||||||
|
for i, loader in ipairs(package.loaders) do
|
||||||
|
if loader == M.loader then
|
||||||
|
table.remove(package.loaders, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
M.enabled = false
|
M.enabled = false
|
||||||
end
|
end
|
||||||
|
@ -79,82 +85,82 @@ function M.loader(modname)
|
||||||
|
|
||||||
local chunk, err
|
local chunk, err
|
||||||
if entry and M.check_path(modname, entry.modpath) then
|
if entry and M.check_path(modname, entry.modpath) then
|
||||||
entry.used = os.time()
|
chunk, err = M.load(modname, entry.modpath)
|
||||||
local hash = M.hash(entry.modpath)
|
else
|
||||||
if not hash then
|
-- find the modpath and load the module
|
||||||
return
|
local modpath = M.find(modname)
|
||||||
|
if modpath then
|
||||||
|
chunk, err = M.load(modname, modpath)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
return chunk or (err and error(err)) or "not found in lazy cache"
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param modpath string
|
||||||
|
---@return any, string?
|
||||||
|
function M.loadfile(modpath)
|
||||||
|
return M.load(modpath, modpath)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param modkey string
|
||||||
|
---@param modpath string
|
||||||
|
---@return function?, string? error_message
|
||||||
|
function M.load(modkey, modpath)
|
||||||
|
local hash = M.hash(modpath)
|
||||||
|
if not hash then
|
||||||
|
-- trigger correct error
|
||||||
|
return M._loadfile(modpath)
|
||||||
|
end
|
||||||
|
|
||||||
|
local entry = M.cache[modkey]
|
||||||
|
if entry then
|
||||||
|
entry.used = os.time()
|
||||||
if M.eq(entry.hash, hash) then
|
if M.eq(entry.hash, hash) then
|
||||||
-- found in cache and up to date
|
-- found in cache and up to date
|
||||||
chunk, err = load(entry.chunk --[[@as string]], "@" .. entry.modpath)
|
return loadstring(entry.chunk --[[@as string]], "@" .. entry.modpath)
|
||||||
return chunk or error(err)
|
|
||||||
end
|
end
|
||||||
-- reload from file
|
|
||||||
entry.hash = hash
|
|
||||||
chunk, err = loadfile(entry.modpath)
|
|
||||||
else
|
else
|
||||||
-- load the module and find its modpath
|
entry = { hash = hash, modpath = modpath, used = os.time() }
|
||||||
local modpath
|
M.cache[modkey] = entry
|
||||||
chunk, modpath = M.find(modname)
|
|
||||||
if modpath then
|
|
||||||
entry = { hash = M.hash(modpath), modpath = modpath, used = os.time() }
|
|
||||||
M.cache[modname] = entry
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
entry.hash = hash
|
||||||
|
|
||||||
if M.debug then
|
if M.debug then
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
vim.notify("[cache:load] " .. modname)
|
vim.notify("[cache:load] " .. modpath)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
if entry and chunk then
|
|
||||||
|
local chunk, err = M._loadfile(entry.modpath)
|
||||||
|
if chunk then
|
||||||
M.dirty = true
|
M.dirty = true
|
||||||
entry.chunk = string.dump(chunk)
|
entry.chunk = string.dump(chunk)
|
||||||
end
|
end
|
||||||
return chunk or error(err)
|
return chunk, err
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.require(modname)
|
function M.require(modname)
|
||||||
return M.loader(modname)()
|
return M.loader(modname)()
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.idx()
|
|
||||||
-- update our loader position if needed
|
|
||||||
if package.loaders[M.loader_idx] ~= M.loader then
|
|
||||||
M.loader_idx = nil
|
|
||||||
---@diagnostic disable-next-line: no-unknown
|
|
||||||
for i, loader in ipairs(package.loaders) do
|
|
||||||
if loader == M.loader then
|
|
||||||
M.loader_idx = i
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return M.loader_idx
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param modname string
|
---@param modname string
|
||||||
|
---@return string?
|
||||||
function M.find(modname)
|
function M.find(modname)
|
||||||
if M.idx() then
|
local basename = modname:gsub("%.", "/")
|
||||||
-- find the module and its modpath
|
local paths = { "lua/" .. basename .. ".lua", "lua/" .. basename .. "/init.lua" }
|
||||||
for i = M.loader_idx + 1, #package.loaders do
|
return vim.api.nvim__get_runtime(paths, false, { is_lua = true })[1]
|
||||||
---@diagnostic disable-next-line: no-unknown
|
|
||||||
local chunk = package.loaders[i](modname)
|
|
||||||
if type(chunk) == "function" then
|
|
||||||
local info = debug.getinfo(chunk, "S")
|
|
||||||
return chunk, (info.what ~= "C" and info.source:sub(2))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- returns the cached RTP excluding plugin dirs
|
||||||
function M.get_rtp()
|
function M.get_rtp()
|
||||||
if not M.rtp then
|
if not M.rtp then
|
||||||
M.rtp = {}
|
M.rtp = {}
|
||||||
|
---@type table<string,true>
|
||||||
local skip = {}
|
local skip = {}
|
||||||
-- only skip plugins once Config has been setup
|
-- only skip plugins once Config has been setup
|
||||||
if package.loaded["lazy.core.config"] then
|
if package.loaded["lazy.core.config"] then
|
||||||
local Config = require("lazy.core.config")
|
local Config = require("lazy.core.config")
|
||||||
for _, plugin in ipairs(Config.plugins) do
|
for _, plugin in pairs(Config.plugins) do
|
||||||
if plugin.name ~= "lazy.nvim" then
|
if plugin.name ~= "lazy.nvim" then
|
||||||
skip[plugin.dir] = true
|
skip[plugin.dir] = true
|
||||||
end
|
end
|
||||||
|
@ -173,14 +179,18 @@ end
|
||||||
function M.setup(opts)
|
function M.setup(opts)
|
||||||
-- no fancy deep extend here. just set the options
|
-- no fancy deep extend here. just set the options
|
||||||
if opts and opts.performance and opts.performance.cache then
|
if opts and opts.performance and opts.performance.cache then
|
||||||
|
---@diagnostic disable-next-line: no-unknown
|
||||||
for k, v in pairs(opts.performance.cache) do
|
for k, v in pairs(opts.performance.cache) do
|
||||||
|
---@diagnostic disable-next-line: no-unknown
|
||||||
M.config[k] = v
|
M.config[k] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
M.debug = opts and opts.debug
|
M.debug = opts and opts.debug
|
||||||
|
|
||||||
M.load_cache()
|
M.load_cache()
|
||||||
table.insert(package.loaders, M.loader_idx, M.loader)
|
table.insert(package.loaders, 2, M.loader)
|
||||||
|
-- selene:allow(global_usage)
|
||||||
|
_G.loadfile = M.loadfile
|
||||||
|
|
||||||
-- reset rtp when it changes
|
-- reset rtp when it changes
|
||||||
vim.api.nvim_create_autocmd("OptionSet", {
|
vim.api.nvim_create_autocmd("OptionSet", {
|
||||||
|
|
Loading…
Reference in New Issue