mirror of https://github.com/folke/lazy.nvim.git
refactor: prepping for vim.loader
This commit is contained in:
parent
887eb75591
commit
690f9e88e2
|
@ -26,32 +26,34 @@ local M = {}
|
||||||
---@field modname string Name of the module
|
---@field modname string Name of the module
|
||||||
---@field stat? uv_fs_t File stat of the module path
|
---@field stat? uv_fs_t File stat of the module path
|
||||||
|
|
||||||
M.VERSION = 3
|
---@alias LoaderStats table<string, {total:number, time:number, [string]:number?}?>
|
||||||
|
|
||||||
M.path = vim.fn.stdpath("cache") .. "/luac"
|
M.path = vim.fn.stdpath("cache") .. "/luac"
|
||||||
M.enabled = false
|
M.enabled = false
|
||||||
---@type table<string, {total:number, time:number, [string]:number?}?>
|
|
||||||
M.stats = {
|
|
||||||
find = { total = 0, time = 0, not_found = 0 },
|
|
||||||
}
|
|
||||||
|
|
||||||
---@class Loader
|
---@class Loader
|
||||||
---@field _rtp string[]
|
---@field _rtp string[]
|
||||||
---@field _rtp_pure string[]
|
---@field _rtp_pure string[]
|
||||||
---@field _rtp_key string
|
---@field _rtp_key string
|
||||||
local Loader = {
|
local Loader = {
|
||||||
|
VERSION = 3,
|
||||||
---@type table<string, table<string,ModuleInfo>>
|
---@type table<string, table<string,ModuleInfo>>
|
||||||
_indexed = {},
|
_indexed = {},
|
||||||
---@type table<string, string[]>
|
---@type table<string, string[]>
|
||||||
_topmods = {},
|
_topmods = {},
|
||||||
_loadfile = loadfile,
|
_loadfile = loadfile,
|
||||||
|
---@type LoaderStats
|
||||||
|
_stats = {
|
||||||
|
find = { total = 0, time = 0, not_found = 0 },
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Tracks the time spent in a function
|
--- Tracks the time spent in a function
|
||||||
---@private
|
---@private
|
||||||
function M._track(stat, start)
|
function Loader.track(stat, start)
|
||||||
M.stats[stat] = M.stats[stat] or { total = 0, time = 0 }
|
Loader._stats[stat] = Loader._stats[stat] or { total = 0, time = 0 }
|
||||||
M.stats[stat].total = M.stats[stat].total + 1
|
Loader._stats[stat].total = Loader._stats[stat].total + 1
|
||||||
M.stats[stat].time = M.stats[stat].time + uv.hrtime() - start
|
Loader._stats[stat].time = Loader._stats[stat].time + uv.hrtime() - start
|
||||||
end
|
end
|
||||||
|
|
||||||
--- slightly faster/different version than vim.fs.normalize
|
--- slightly faster/different version than vim.fs.normalize
|
||||||
|
@ -77,7 +79,7 @@ end
|
||||||
function Loader.get_rtp()
|
function Loader.get_rtp()
|
||||||
local start = uv.hrtime()
|
local start = uv.hrtime()
|
||||||
if vim.in_fast_event() then
|
if vim.in_fast_event() then
|
||||||
M._track("get_rtp", start)
|
Loader.track("get_rtp", start)
|
||||||
return (Loader._rtp or {}), false
|
return (Loader._rtp or {}), false
|
||||||
end
|
end
|
||||||
local updated = false
|
local updated = false
|
||||||
|
@ -94,7 +96,7 @@ function Loader.get_rtp()
|
||||||
updated = true
|
updated = true
|
||||||
Loader._rtp_key = key
|
Loader._rtp_key = key
|
||||||
end
|
end
|
||||||
M._track("get_rtp", start)
|
Loader.track("get_rtp", start)
|
||||||
return Loader._rtp, updated
|
return Loader._rtp, updated
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -115,7 +117,7 @@ function Loader.write(name, entry)
|
||||||
local cname = Loader.cache_file(name)
|
local cname = Loader.cache_file(name)
|
||||||
local f = assert(uv.fs_open(cname, "w", 438))
|
local f = assert(uv.fs_open(cname, "w", 438))
|
||||||
local header = {
|
local header = {
|
||||||
M.VERSION,
|
Loader.VERSION,
|
||||||
entry.hash.size,
|
entry.hash.size,
|
||||||
entry.hash.mtime.sec,
|
entry.hash.mtime.sec,
|
||||||
entry.hash.mtime.nsec,
|
entry.hash.mtime.nsec,
|
||||||
|
@ -142,16 +144,16 @@ function Loader.read(name)
|
||||||
|
|
||||||
---@type integer[]|{[0]:integer}
|
---@type integer[]|{[0]:integer}
|
||||||
local header = vim.split(data:sub(1, zero - 1), ",")
|
local header = vim.split(data:sub(1, zero - 1), ",")
|
||||||
if tonumber(header[1]) ~= M.VERSION then
|
if tonumber(header[1]) ~= Loader.VERSION then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
M._track("read", start)
|
Loader.track("read", start)
|
||||||
return {
|
return {
|
||||||
hash = { size = tonumber(header[2]), mtime = { sec = tonumber(header[3]), nsec = tonumber(header[4]) } },
|
hash = { size = tonumber(header[2]), mtime = { sec = tonumber(header[3]), nsec = tonumber(header[4]) } },
|
||||||
chunk = data:sub(zero + 1),
|
chunk = data:sub(zero + 1),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
M._track("read", start)
|
Loader.track("read", start)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- The `package.loaders` loader for lua files using the cache.
|
--- The `package.loaders` loader for lua files using the cache.
|
||||||
|
@ -163,10 +165,10 @@ function Loader.loader(modname)
|
||||||
local ret = M.find(modname)[1]
|
local ret = M.find(modname)[1]
|
||||||
if ret then
|
if ret then
|
||||||
local chunk, err = Loader.load(ret.modpath, { hash = ret.stat })
|
local chunk, err = Loader.load(ret.modpath, { hash = ret.stat })
|
||||||
M._track("loader", start)
|
Loader.track("loader", start)
|
||||||
return chunk or error(err)
|
return chunk or error(err)
|
||||||
end
|
end
|
||||||
M._track("loader", start)
|
Loader.track("loader", start)
|
||||||
return "\ncache_loader: module " .. modname .. " not found"
|
return "\ncache_loader: module " .. modname .. " not found"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -189,10 +191,10 @@ function Loader.loader_lib(modname)
|
||||||
local dash = modname:find("-", 1, true)
|
local dash = modname:find("-", 1, true)
|
||||||
local funcname = dash and modname:sub(dash + 1) or modname
|
local funcname = dash and modname:sub(dash + 1) or modname
|
||||||
local chunk, err = package.loadlib(ret.modpath, "luaopen_" .. funcname:gsub("%.", "_"))
|
local chunk, err = package.loadlib(ret.modpath, "luaopen_" .. funcname:gsub("%.", "_"))
|
||||||
M._track("loader_lib", start)
|
Loader.track("loader_lib", start)
|
||||||
return chunk or error(err)
|
return chunk or error(err)
|
||||||
end
|
end
|
||||||
M._track("loader_lib", start)
|
Loader.track("loader_lib", start)
|
||||||
return "\ncache_loader_lib: module " .. modname .. " not found"
|
return "\ncache_loader_lib: module " .. modname .. " not found"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -209,7 +211,7 @@ function Loader.loadfile(filename, mode, env, hash)
|
||||||
filename = Loader.normalize(filename)
|
filename = Loader.normalize(filename)
|
||||||
mode = nil -- ignore mode, since we byte-compile the lua source files
|
mode = nil -- ignore mode, since we byte-compile the lua source files
|
||||||
local chunk, err = Loader.load(filename, { mode = mode, env = env, hash = hash })
|
local chunk, err = Loader.load(filename, { mode = mode, env = env, hash = hash })
|
||||||
M._track("loadfile", start)
|
Loader.track("loadfile", start)
|
||||||
return chunk, err
|
return chunk, err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -244,7 +246,7 @@ function Loader.load(modpath, opts)
|
||||||
if not hash then
|
if not hash then
|
||||||
-- trigger correct error
|
-- trigger correct error
|
||||||
chunk, err = Loader._loadfile(modpath, opts.mode, opts.env)
|
chunk, err = Loader._loadfile(modpath, opts.mode, opts.env)
|
||||||
M._track("load", start)
|
Loader.track("load", start)
|
||||||
return chunk, err
|
return chunk, err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -254,7 +256,7 @@ function Loader.load(modpath, opts)
|
||||||
-- selene: allow(incorrect_standard_library_use)
|
-- selene: allow(incorrect_standard_library_use)
|
||||||
chunk, err = load(entry.chunk --[[@as string]], "@" .. modpath, opts.mode, opts.env)
|
chunk, err = load(entry.chunk --[[@as string]], "@" .. modpath, opts.mode, opts.env)
|
||||||
if not (err and err:find("cannot load incompatible bytecode", 1, true)) then
|
if not (err and err:find("cannot load incompatible bytecode", 1, true)) then
|
||||||
M._track("load", start)
|
Loader.track("load", start)
|
||||||
return chunk, err
|
return chunk, err
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -265,7 +267,7 @@ function Loader.load(modpath, opts)
|
||||||
entry.chunk = string.dump(chunk)
|
entry.chunk = string.dump(chunk)
|
||||||
Loader.write(modpath, entry)
|
Loader.write(modpath, entry)
|
||||||
end
|
end
|
||||||
M._track("load", start)
|
Loader.track("load", start)
|
||||||
return chunk, err
|
return chunk, err
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -332,7 +334,7 @@ function M.find(modname, opts)
|
||||||
elseif Loader.lsmod(path)[topmod] then
|
elseif Loader.lsmod(path)[topmod] then
|
||||||
for _, pattern in ipairs(patterns) do
|
for _, pattern in ipairs(patterns) do
|
||||||
local modpath = path .. pattern
|
local modpath = path .. pattern
|
||||||
M.stats.find.stat = (M.stats.find.stat or 0) + 1
|
Loader._stats.find.stat = (Loader._stats.find.stat or 0) + 1
|
||||||
local hash = uv.fs_stat(modpath)
|
local hash = uv.fs_stat(modpath)
|
||||||
if hash then
|
if hash then
|
||||||
results[#results + 1] = { modpath = modpath, stat = hash, modname = modname }
|
results[#results + 1] = { modpath = modpath, stat = hash, modname = modname }
|
||||||
|
@ -361,10 +363,10 @@ function M.find(modname, opts)
|
||||||
_find(opts.paths)
|
_find(opts.paths)
|
||||||
end
|
end
|
||||||
|
|
||||||
M._track("find", start)
|
Loader.track("find", start)
|
||||||
if #results == 0 then
|
if #results == 0 then
|
||||||
-- module not found
|
-- module not found
|
||||||
M.stats.find.not_found = M.stats.find.not_found + 1
|
Loader._stats.find.not_found = Loader._stats.find.not_found + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
@ -474,48 +476,51 @@ function Loader.lsmod(path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
M._track("lsmod", start)
|
Loader.track("lsmod", start)
|
||||||
end
|
end
|
||||||
return Loader._indexed[path]
|
return Loader._indexed[path]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Debug function that wrapps all loaders and tracks stats
|
--- Debug function that wrapps all loaders and tracks stats
|
||||||
---@private
|
---@private
|
||||||
function M.profile_loaders()
|
function M._profile_loaders()
|
||||||
for l, loader in pairs(package.loaders) do
|
for l, loader in pairs(package.loaders) do
|
||||||
local loc = debug.getinfo(loader, "Sn").source:sub(2)
|
local loc = debug.getinfo(loader, "Sn").source:sub(2)
|
||||||
package.loaders[l] = function(modname)
|
package.loaders[l] = function(modname)
|
||||||
local start = vim.loop.hrtime()
|
local start = vim.loop.hrtime()
|
||||||
local ret = loader(modname)
|
local ret = loader(modname)
|
||||||
M._track("loader " .. l .. ": " .. loc, start)
|
Loader.track("loader " .. l .. ": " .. loc, start)
|
||||||
M._track("loader_all", start)
|
Loader.track("loader_all", start)
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Prints all cache stats
|
--- Prints all cache stats
|
||||||
|
---@param opts? {print?:boolean}
|
||||||
|
---@return LoaderStats
|
||||||
---@private
|
---@private
|
||||||
function M.inspect()
|
function M._inspect(opts)
|
||||||
|
if opts and opts.print then
|
||||||
---@private
|
---@private
|
||||||
local function ms(nsec)
|
local function ms(nsec)
|
||||||
return math.floor(nsec / 1e6 * 1000 + 0.5) / 1000 .. "ms"
|
return math.floor(nsec / 1e6 * 1000 + 0.5) / 1000 .. "ms"
|
||||||
end
|
end
|
||||||
local chunks = {} ---@type string[][]
|
local chunks = {} ---@type string[][]
|
||||||
---@type string[]
|
---@type string[]
|
||||||
local stats = vim.tbl_keys(M.stats)
|
local stats = vim.tbl_keys(Loader._stats)
|
||||||
table.sort(stats)
|
table.sort(stats)
|
||||||
for _, stat in ipairs(stats) do
|
for _, stat in ipairs(stats) do
|
||||||
vim.list_extend(chunks, {
|
vim.list_extend(chunks, {
|
||||||
{ "\n" .. stat .. "\n", "Title" },
|
{ "\n" .. stat .. "\n", "Title" },
|
||||||
{ "* total: " },
|
{ "* total: " },
|
||||||
{ tostring(M.stats[stat].total) .. "\n", "Number" },
|
{ tostring(Loader._stats[stat].total) .. "\n", "Number" },
|
||||||
{ "* time: " },
|
{ "* time: " },
|
||||||
{ ms(M.stats[stat].time) .. "\n", "Bold" },
|
{ ms(Loader._stats[stat].time) .. "\n", "Bold" },
|
||||||
{ "* avg time: " },
|
{ "* avg time: " },
|
||||||
{ ms(M.stats[stat].time / M.stats[stat].total) .. "\n", "Bold" },
|
{ ms(Loader._stats[stat].time / Loader._stats[stat].total) .. "\n", "Bold" },
|
||||||
})
|
})
|
||||||
for k, v in pairs(M.stats[stat]) do
|
for k, v in pairs(Loader._stats[stat]) do
|
||||||
if not vim.tbl_contains({ "time", "total" }, k) then
|
if not vim.tbl_contains({ "time", "total" }, k) then
|
||||||
chunks[#chunks + 1] = { "* " .. k .. ":" .. string.rep(" ", 9 - #k) }
|
chunks[#chunks + 1] = { "* " .. k .. ":" .. string.rep(" ", 9 - #k) }
|
||||||
chunks[#chunks + 1] = { tostring(v) .. "\n", "Number" }
|
chunks[#chunks + 1] = { tostring(v) .. "\n", "Number" }
|
||||||
|
@ -523,8 +528,8 @@ function M.inspect()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
vim.api.nvim_echo(chunks, true, {})
|
vim.api.nvim_echo(chunks, true, {})
|
||||||
|
end
|
||||||
|
return Loader._stats
|
||||||
end
|
end
|
||||||
|
|
||||||
M._Cache = Loader
|
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
@ -675,7 +675,7 @@ function M:debug()
|
||||||
end)
|
end)
|
||||||
self:nl()
|
self:nl()
|
||||||
|
|
||||||
Util.foreach(require("lazy.core.cache").stats, function(name, stats)
|
Util.foreach(require("lazy.core.cache")._inspect(), function(name, stats)
|
||||||
self:append(name, "LazyH2"):nl()
|
self:append(name, "LazyH2"):nl()
|
||||||
local props = {
|
local props = {
|
||||||
{ "total", stats.total or 0, "Number" },
|
{ "total", stats.total or 0, "Number" },
|
||||||
|
|
Loading…
Reference in New Issue