perf: caching strategy is now configurable

This commit is contained in:
Folke Lemaitre 2022-12-02 12:43:34 +01:00
parent ae379a62dc
commit 6fe425c91a
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
3 changed files with 89 additions and 29 deletions

View File

@ -5,7 +5,19 @@ local uv = vim.loop
local M = {} local M = {}
M.dirty = false M.dirty = false
local cache_path = vim.fn.stdpath("state") .. "/lazy.state" ---@class LazyCacheConfig
M.config = {
enabled = true,
path = vim.fn.stdpath("state") .. "/lazy.state",
-- choose what should be cached
-- * lazy: cache all lazy.nvim core modules and your config files
-- * init: all of the above and any module needed to init your plugins
-- * VimEnter: any module till VimEnter
-- * VeryLazy: any module till VeryLazy
-- * allthethings: all mdules. Not recommended
strategy = "VimEnter", ---@type "lazy"|"init"|"VimEnter"|"allthethings"
}
---@type CacheHash ---@type CacheHash
local cache_hash local cache_hash
@ -27,13 +39,25 @@ function M.check_load(modname, modpath)
require("lazy.core.loader").autoload(modname, modpath) require("lazy.core.loader").autoload(modname, modpath)
end end
---@param step? string
function M.disable(step)
if not M.enabled then
return
end
if step and M.config.strategy ~= step then
return
end
local idx = M.idx()
if idx then
table.remove(package.loaders, idx)
end
M.enabled = false
end
---@param modname string ---@param modname string
---@return any ---@return any
function M.loader(modname) function M.loader(modname)
if not M.enabled then
return "lazy loader is disabled"
end
local entry = M.cache[modname] local entry = M.cache[modname]
local chunk, err local chunk, err
@ -68,11 +92,10 @@ function M.loader(modname)
return chunk or error(err) return chunk or error(err)
end end
---@param modname string function M.idx()
function M.find(modname)
-- update our loader position if needed -- update our loader position if needed
if package.loaders[M.loader_idx] ~= M.loader then if package.loaders[M.loader_idx] ~= M.loader then
M.loader_idx = 1 M.loader_idx = nil
---@diagnostic disable-next-line: no-unknown ---@diagnostic disable-next-line: no-unknown
for i, loader in ipairs(package.loaders) do for i, loader in ipairs(package.loaders) do
if loader == M.loader then if loader == M.loader then
@ -81,29 +104,49 @@ function M.find(modname)
end end
end end
end end
return M.loader_idx
end
-- find the module and its modpath ---@param modname string
for i = M.loader_idx + 1, #package.loaders do function M.find(modname)
---@diagnostic disable-next-line: no-unknown if M.idx() then
local chunk = package.loaders[i](modname) -- find the module and its modpath
if type(chunk) == "function" then for i = M.loader_idx + 1, #package.loaders do
local info = debug.getinfo(chunk, "S") ---@diagnostic disable-next-line: no-unknown
return chunk, (info.what ~= "C" and info.source:sub(2)) 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
end end
function M.setup() ---@param opts? LazyConfig
function M.setup(opts)
-- no fancy deep extend here. just set the options
if opts and opts.performance and opts.performance.cache then
for k, v in pairs(opts.performance.cache) do
M.config[k] = v
end
end
M.load_cache() M.load_cache()
table.insert(package.loaders, M.loader_idx, M.loader) table.insert(package.loaders, M.loader_idx, M.loader)
vim.api.nvim_create_autocmd("VimEnter", { if M.config.strategy == "VimEnter" then
once = true, vim.api.nvim_create_autocmd("VimEnter", {
callback = function() once = true,
-- startup done, so stop caching callback = function()
M.enabled = false -- use schedule so all other VimEnter handlers will have run
end, vim.schedule(function()
}) -- startup done, so stop caching
M.disable()
end)
end,
})
end
return M
end end
---@return CacheHash? ---@return CacheHash?
@ -118,7 +161,7 @@ function M.eq(h1, h2)
end end
function M.save_cache() function M.save_cache()
local f = assert(uv.fs_open(cache_path, "w", 438)) local f = assert(uv.fs_open(M.config.path, "w", 438))
for modname, entry in pairs(M.cache) do for modname, entry in pairs(M.cache) do
if entry.used > os.time() - M.ttl then if entry.used > os.time() - M.ttl then
entry.modname = modname entry.modname = modname
@ -142,7 +185,7 @@ end
function M.load_cache() function M.load_cache()
M.cache = {} M.cache = {}
local f = uv.fs_open(cache_path, "r", 438) local f = uv.fs_open(M.config.path, "r", 438)
if f then if f then
cache_hash = uv.fs_fstat(f) --[[@as CacheHash]] cache_hash = uv.fs_fstat(f) --[[@as CacheHash]]
local data = uv.fs_read(f, cache_hash.size, 0) --[[@as string]] local data = uv.fs_read(f, cache_hash.size, 0) --[[@as string]]
@ -172,7 +215,7 @@ function M.autosave()
vim.api.nvim_create_autocmd("VimLeavePre", { vim.api.nvim_create_autocmd("VimLeavePre", {
callback = function() callback = function()
if M.dirty then if M.dirty then
local hash = M.hash(cache_path) local hash = M.hash(M.config.path)
-- abort when the file was changed in the meantime -- abort when the file was changed in the meantime
if hash == nil or M.eq(cache_hash, hash) then if hash == nil or M.eq(cache_hash, hash) then
M.save_cache() M.save_cache()

View File

@ -48,6 +48,10 @@ M.defaults = {
}, },
throttle = 20, -- how frequently should the ui process render events throttle = 20, -- how frequently should the ui process render events
}, },
performance = {
---@type LazyCacheConfig
cache = nil,
},
} }
M.ns = vim.api.nvim_create_namespace("lazy") M.ns = vim.api.nvim_create_namespace("lazy")
@ -72,6 +76,7 @@ M.options = {}
function M.setup(spec, opts) function M.setup(spec, opts)
M.spec = spec M.spec = spec
M.options = vim.tbl_deep_extend("force", M.defaults, opts or {}) M.options = vim.tbl_deep_extend("force", M.defaults, opts or {})
M.options.performance.cache = require("lazy.core.cache")
M.root = M.options.package.path .. "/pack/" .. M.options.package.name .. "/opt" M.root = M.options.package.path .. "/pack/" .. M.options.package.name .. "/opt"
if M.options.package.reset then if M.options.package.reset then
@ -84,7 +89,7 @@ function M.setup(spec, opts)
pattern = "VeryLazy", pattern = "VeryLazy",
once = true, once = true,
callback = function() callback = function()
require("lazy.core.module").autosave() require("lazy.core.cache").autosave()
require("lazy.view").setup() require("lazy.view").setup()
end, end,
}) })

View File

@ -8,8 +8,12 @@ function M.setup(spec, opts)
end end
local start = vim.loop.hrtime() local start = vim.loop.hrtime()
-- load module cache before anything else local Cache
require("lazy.core.module").setup() if not (opts and opts.performance and opts.performance.cache and opts.performance.cache.enabled == false) then
-- load module cache before anything else
Cache = require("lazy.core.cache").setup(opts)
end
local Util = require("lazy.core.util") local Util = require("lazy.core.util")
local Config = require("lazy.core.config") local Config = require("lazy.core.config")
local Loader = require("lazy.core.loader") local Loader = require("lazy.core.loader")
@ -36,9 +40,17 @@ function M.setup(spec, opts)
Config.plugins["lazy.nvim"]._.loaded = { time = delta, source = "init.lua" } Config.plugins["lazy.nvim"]._.loaded = { time = delta, source = "init.lua" }
end end
if Cache then
Cache.disable("lazy")
end
-- load plugins with lazy=false or Plugin.init -- load plugins with lazy=false or Plugin.init
Loader.init_plugins() Loader.init_plugins()
if Cache then
Cache.disable("init")
end
-- all done! -- all done!
vim.cmd("do User LazyDone") vim.cmd("do User LazyDone")
end end