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 = {}
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
local cache_hash
@ -27,13 +39,25 @@ function M.check_load(modname, modpath)
require("lazy.core.loader").autoload(modname, modpath)
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
---@return any
function M.loader(modname)
if not M.enabled then
return "lazy loader is disabled"
end
local entry = M.cache[modname]
local chunk, err
@ -68,11 +92,10 @@ function M.loader(modname)
return chunk or error(err)
end
---@param modname string
function M.find(modname)
function M.idx()
-- update our loader position if needed
if package.loaders[M.loader_idx] ~= M.loader then
M.loader_idx = 1
M.loader_idx = nil
---@diagnostic disable-next-line: no-unknown
for i, loader in ipairs(package.loaders) do
if loader == M.loader then
@ -81,29 +104,49 @@ function M.find(modname)
end
end
end
return M.loader_idx
end
-- find the module and its modpath
for i = M.loader_idx + 1, #package.loaders do
---@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))
---@param modname string
function M.find(modname)
if M.idx() then
-- find the module and its modpath
for i = M.loader_idx + 1, #package.loaders do
---@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
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()
table.insert(package.loaders, M.loader_idx, M.loader)
vim.api.nvim_create_autocmd("VimEnter", {
once = true,
callback = function()
-- startup done, so stop caching
M.enabled = false
end,
})
if M.config.strategy == "VimEnter" then
vim.api.nvim_create_autocmd("VimEnter", {
once = true,
callback = function()
-- use schedule so all other VimEnter handlers will have run
vim.schedule(function()
-- startup done, so stop caching
M.disable()
end)
end,
})
end
return M
end
---@return CacheHash?
@ -118,7 +161,7 @@ function M.eq(h1, h2)
end
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
if entry.used > os.time() - M.ttl then
entry.modname = modname
@ -142,7 +185,7 @@ end
function M.load_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
cache_hash = uv.fs_fstat(f) --[[@as CacheHash]]
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", {
callback = function()
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
if hash == nil or M.eq(cache_hash, hash) then
M.save_cache()

View File

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

View File

@ -8,8 +8,12 @@ function M.setup(spec, opts)
end
local start = vim.loop.hrtime()
-- load module cache before anything else
require("lazy.core.module").setup()
local Cache
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 Config = require("lazy.core.config")
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" }
end
if Cache then
Cache.disable("lazy")
end
-- load plugins with lazy=false or Plugin.init
Loader.init_plugins()
if Cache then
Cache.disable("init")
end
-- all done!
vim.cmd("do User LazyDone")
end