Skip to content

Commit

Permalink
perf: tons of performance improvements. Lazy should now load in about…
Browse files Browse the repository at this point in the history
… 1.5ms for 97 plugins
  • Loading branch information
folke committed Nov 24, 2022
1 parent 711834f commit 2507fd5
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 272 deletions.
1 change: 1 addition & 0 deletions lua/lazy/core/cache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ local used = {}
---@type table<string,string>
local cache = {}

---@return string?
function M.get(key)
if cache[key] then
used[key] = true
Expand Down
13 changes: 13 additions & 0 deletions lua/lazy/core/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ M.defaults = {
plugins = "config.plugins",
plugins_local = {
path = vim.fn.expand("~/projects"),
---@type string[]
patterns = {},
},
package_path = vim.fn.stdpath("data") .. "/site/pack/lazy",
Expand All @@ -27,15 +28,27 @@ M.defaults = {

M.ns = vim.api.nvim_create_namespace("lazy")

M.paths = {
---@type string
main = nil,
---@type string
plugins = nil,
}

---@type table<string, LazyPlugin>
M.plugins = {}

---@type LazyPlugin[]
M.to_clean = {}

---@type LazyConfig
M.options = {}

---@param opts? LazyConfig
function M.setup(opts)
M.options = vim.tbl_deep_extend("force", M.defaults, opts or {})
M.paths.plugins = vim.fn.stdpath("config") .. "/lua/" .. M.options.plugins:gsub("%.", "/")
M.paths.main = M.paths.plugins .. (vim.loop.fs_stat(M.paths.plugins .. ".lua") and ".lua" or "/init.lua")

-- vim.fn.mkdir(M.options.package_path, "p")

Expand Down
27 changes: 13 additions & 14 deletions lua/lazy/core/loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ M.loading = {}

---@param plugin LazyPlugin
function M.add(plugin)
if plugin.init or (plugin.opt == false and plugin.config) then
if plugin.init or (plugin.opt == false) then
table.insert(M.loaders.init, plugin.name)
end

for _, loader_type in ipairs(M.types) do
---@type (string|string[])?
local loaders = plugin[loader_type]
if plugin[loader_type] then
loaders = type(loaders) == "table" and loaders or { loaders }
Expand Down Expand Up @@ -198,7 +199,8 @@ end

---@param plugins string|LazyPlugin|string[]|LazyPlugin[]
---@param reason {[string]:string}
function M.load(plugins, reason)
---@param opts? {load_start: boolean}
function M.load(plugins, reason, opts)
if type(plugins) == "string" or plugins.name then
---@diagnostic disable-next-line: assign-type-mismatch
plugins = { plugins }
Expand All @@ -211,6 +213,7 @@ function M.load(plugins, reason)
end

if not plugin.loaded then
---@diagnostic disable-next-line: assign-type-mismatch
plugin.loaded = {}
for k, v in pairs(reason) do
plugin.loaded[k] = v
Expand All @@ -222,7 +225,7 @@ function M.load(plugins, reason)
table.insert(M.loading, plugin)

Util.track(plugin.name)
M.packadd(plugin)
M.packadd(plugin, opts and opts.load_start)

if plugin.requires then
M.load(plugin.requires, {})
Expand All @@ -242,11 +245,11 @@ function M.load(plugins, reason)
end

---@param plugin LazyPlugin
function M.packadd(plugin)
function M.packadd(plugin, load_start)
if plugin.opt then
vim.cmd.packadd(plugin.pack)
M.source_plugin_files(plugin, true)
else
elseif load_start then
vim.opt.runtimepath:append(plugin.dir)
M.source_plugin_files(plugin)
M.source_plugin_files(plugin, true)
Expand All @@ -256,16 +259,12 @@ end
---@param plugin LazyPlugin
---@param after? boolean
function M.source_plugin_files(plugin, after)
local pattern = (after and "/after" or "") .. ("/plugin/" .. "**/*.\\(vim\\|lua\\)")

local _, entries = pcall(vim.fn.glob, plugin.dir .. "/" .. pattern, false, true)

if entries then
---@cast entries string[]
for _, file in ipairs(entries) do
vim.cmd("silent source " .. file)
Util.walk(plugin.dir .. (after and "/after" or "") .. "/plugin", function(path, _, t)
local ext = path:sub(-3)
if t == "file" and (ext == "lua" or ext == "vim") then
vim.cmd("silent source " .. path)
end
end
end)
end

return M
136 changes: 38 additions & 98 deletions lua/lazy/core/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,132 +2,72 @@ local Cache = require("lazy.core.cache")

local M = {}

---@type table<string, {file: string, hash?:string}>
M.modules = {}
---@type table<string, string>
M.hashes = {}

function M.add(modname, file)
if not M.modules[modname] then
M.modules[modname] = { file = file }
end
function M.is_dirty(modname, modpath)
return not (Cache.get(modname) and M.hashes[modname] and M.hashes[modname] == Cache.hash(modpath))
end

---@param modname string
function M.load(modname)
if type(package.loaded[modname]) == "table" then
return package.loaded[modname]
end

local info = M.modules[modname]
if info then
local err
---@type string|fun()|nil
local chunk = Cache.get(modname)

if not chunk then
vim.schedule(function()
vim.notify("loading " .. modname)
end)
chunk, err = loadfile(info.file)
if chunk then
Cache.set(modname, string.dump(chunk))
info.hash = info.hash or Cache.hash(info.file)
end
---@param modpath string
---@return table
function M.load(modname, modpath)
local err
---@type (string|fun())?
local chunk = Cache.get(modname)

if chunk then
local hash = Cache.hash(modpath)
if hash ~= M.hashes[modname] then
M.hashes[modname] = hash
chunk = nil
end

if type(chunk) == "string" then
chunk, err = loadstring(chunk --[[@as string]], "@" .. info.file)
end

if not chunk then
error(err)
end

---@type table
local mod = chunk()
package.loaded[modname] = mod
return mod
end
end

local function _add_module(dir, modname)
local d = vim.loop.fs_opendir(dir, nil, 100)
if d then
---@type {name: string, type: "file"|"directory"|"link"}[]
local entries = vim.loop.fs_readdir(d)
while entries do
for _, entry in ipairs(entries) do
local path = dir .. "/" .. entry.name
if entry.type == "directory" then
_add_module(path, modname and (modname .. "." .. entry.name) or entry.name)
else
local childname = entry.name:match("^(.*)%.lua$")
if childname then
local child = entry.name == "init.lua" and modname or modname and (modname .. "." .. childname) or childname
if child then
M.add(child, path)
end
end
end
end
entries = vim.loop.fs_readdir(d)
if chunk then
chunk, err = loadstring(chunk --[[@as string]], "@" .. modpath)
else
vim.schedule(function()
vim.notify("loadfile(" .. modname .. ")")
end)
chunk, err = loadfile(modpath)
if chunk then
Cache.set(modname, string.dump(chunk))
M.hashes[modname] = M.hashes[modname] or Cache.hash(modpath)
end
vim.loop.fs_closedir(d)
end
end

function M.add_module(path)
if path:find("/lua/?$") then
return _add_module(path)
end
---@type string
local modname = path:match("/lua/(.*)/?")
assert(modname)
modname = modname:gsub("/", ".")
if vim.loop.fs_stat(path .. ".lua") then
M.add(modname, path .. ".lua")
if chunk then
---@diagnostic disable-next-line: no-unknown
package.loaded[modname] = chunk()
return package.loaded[modname]
else
error(err)
end
_add_module(path, modname)
end

function M.setup()
-- load cache
local value = Cache.get("cache.modules")
if value then
M.modules = vim.json.decode(value)
for k, v in pairs(M.modules) do
if Cache.hash(v.file) ~= v.hash then
Cache.del(k)
M.changed = true
M.modules[k] = nil
end
end
M.hashes = vim.json.decode(value)
end

-- preload core modules
local root = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":p:h:h")
for _, name in ipairs({ "util", "config", "loader", "state" }) do
local modname = "lazy.core." .. name
M.add(modname, root .. "/core/" .. name:gsub("%.", "/") .. ".lua")
end

table.insert(package.loaders, 2, function(modname)
if M.modules[modname] then
return function()
return M.load(modname)
end
---@diagnostic disable-next-line: no-unknown
package.preload[modname] = function()
return M.load(modname, root .. "/core/" .. name:gsub("%.", "/") .. ".lua")
end
end)
end
return M
end

function M.save()
local value = {}
for k, v in pairs(M.modules) do
if v.hash then
value[k] = v
end
end
Cache.set("cache.modules", vim.json.encode(value))
Cache.set("cache.modules", vim.json.encode(M.hashes))
end

return M

0 comments on commit 2507fd5

Please sign in to comment.