feat: added profiler view

This commit is contained in:
Folke Lemaitre 2022-11-29 12:02:25 +01:00
parent 08b7e42fb0
commit 20ff5fa218
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
9 changed files with 81 additions and 61 deletions

View File

@ -25,9 +25,9 @@
- [ ] health checks: check merge conflicts async - [ ] health checks: check merge conflicts async
- [ ] defaults for git log - [ ] defaults for git log
- [ ] view keybindings for update/clean/... - [x] view keybindings for update/clean/...
- [ ] add profiler to view - [x] add profiler to view
- [ ] add buttons for actions - [x] add buttons for actions
- [x] show time taken for op in view - [x] show time taken for op in view
- [ ] package meta index (package.lua cache for all packages) - [ ] package meta index (package.lua cache for all packages)
- [ ] migrate from Packer - [ ] migrate from Packer

View File

@ -17,7 +17,7 @@ M.defaults = {
view = { view = {
icons = { icons = {
start = "", start = "",
plugin = "", plugin = " ",
source = "", source = "",
config = "", config = "",
event = "", event = "",

View File

@ -53,7 +53,7 @@ function M.handlers.event(grouped)
once = true, once = true,
pattern = pattern, pattern = pattern,
callback = function() callback = function()
Util.track("event: " .. (_event == "User" and pattern or event)) Util.track({ event = event })
Loader.load(plugins, { event = event }) Loader.load(plugins, { event = event })
Util.track() Util.track()
end, end,
@ -67,7 +67,7 @@ function M.handlers.keys(grouped)
---@cast keys string ---@cast keys string
vim.keymap.set("n", keys, function() vim.keymap.set("n", keys, function()
vim.keymap.del("n", keys) vim.keymap.del("n", keys)
Util.track("keys: " .. keys) Util.track({ keys = keys })
Loader.load(plugins, { keys = keys }) Loader.load(plugins, { keys = keys })
vim.api.nvim_input(keys) vim.api.nvim_input(keys)
Util.track() Util.track()
@ -84,7 +84,7 @@ function M.handlers.ft(grouped)
pattern = ft, pattern = ft,
group = group, group = group,
callback = function() callback = function()
Util.track("filetype: " .. ft) Util.track({ ft = ft })
Loader.load(plugins, { ft = ft }) Loader.load(plugins, { ft = ft })
Util.track() Util.track()
end, end,
@ -95,13 +95,9 @@ end
function M.handlers.cmd(grouped) function M.handlers.cmd(grouped)
for cmd, plugins in pairs(grouped) do for cmd, plugins in pairs(grouped) do
---@cast cmd string ---@cast cmd string
local function _load(complete) local function _load()
vim.api.nvim_del_user_command(cmd) vim.api.nvim_del_user_command(cmd)
if complete then Util.track({ cmd = cmd })
Util.track("cmd-complete: " .. cmd)
else
Util.track("cmd: " .. cmd)
end
Loader.load(plugins, { cmd = cmd }) Loader.load(plugins, { cmd = cmd })
Util.track() Util.track()
end end
@ -120,7 +116,7 @@ function M.handlers.cmd(grouped)
bang = true, bang = true,
nargs = "*", nargs = "*",
complete = function() complete = function()
_load(true) _load()
-- HACK: trick Neovim to show the newly loaded command completion -- HACK: trick Neovim to show the newly loaded command completion
vim.api.nvim_input("<space><bs><tab>") vim.api.nvim_input("<space><bs><tab>")
end, end,

View File

@ -22,7 +22,7 @@ function M.init_plugins()
Util.track("plugin_init") Util.track("plugin_init")
for _, plugin in pairs(Config.plugins) do for _, plugin in pairs(Config.plugins) do
if plugin.init then if plugin.init then
Util.track(plugin.name) Util.track({ plugin = plugin.name, start = "init" })
Util.try(plugin.init, "Failed to run `init` for **" .. plugin.name .. "**") Util.try(plugin.init, "Failed to run `init` for **" .. plugin.name .. "**")
Util.track() Util.track()
end end
@ -58,7 +58,7 @@ function M.load(plugins, reason, opts)
table.insert(M.loading, plugin) table.insert(M.loading, plugin)
Util.track(plugin.name) Util.track({ plugin = plugin.name, start = reason.start })
M.packadd(plugin, opts and opts.load_start) M.packadd(plugin, opts and opts.load_start)
if plugin.requires then if plugin.requires then

View File

@ -1,16 +1,16 @@
local M = {} local M = {}
---@alias LazyProfile {name: string, time: number, [number]:LazyProfile} ---@alias LazyProfile {data: string|{[string]:string}, time: number, [number]:LazyProfile}
---@type LazyProfile[] ---@type LazyProfile[]
M._profiles = { { name = "lazy" } } M._profiles = { { name = "lazy" } }
---@param name string? ---@param data (string|{[string]:string})?
---@param time number? ---@param time number?
function M.track(name, time) function M.track(data, time)
if name then if data then
local entry = { local entry = {
name = name, data = data,
time = time or vim.loop.hrtime(), time = time or vim.loop.hrtime(),
} }
table.insert(M._profiles[#M._profiles], entry) table.insert(M._profiles[#M._profiles], entry)

View File

@ -52,32 +52,6 @@ function M.throttle(ms, fn)
end end
end end
function M.profile()
local lines = { "# Profile" }
---@param entry LazyProfile
local function _profile(entry, depth)
if entry.time < 0.5 then
-- Nothing
end
table.insert(
lines,
(" "):rep(depth) .. "- " .. entry.name .. ": **" .. math.floor((entry.time or 0) / 1e6 * 100) / 100 .. "ms**"
)
for _, child in ipairs(entry) do
_profile(child, depth + 1)
end
end
for _, entry in ipairs(M._profiles[1]) do
_profile(entry, 1)
end
M.markdown(lines)
end
---@return string? ---@return string?
function M.head(file) function M.head(file)
local f = io.open(file) local f = io.open(file)

View File

@ -36,6 +36,9 @@ M.commands = {
help = function() help = function()
View.show("help") View.show("help")
end, end,
profile = function()
View.show("profile")
end,
sync = function() sync = function()
Manage.clean({ interactive = true, clear = true, wait = true, mode = "sync" }) Manage.clean({ interactive = true, clear = true, wait = true, mode = "sync" })
Manage.update({ interactive = true }) Manage.update({ interactive = true })

View File

@ -12,7 +12,8 @@ M.modes = {
{ name = "check", key = "C", desc = "Check for updates and show the log (git fetch)" }, { name = "check", key = "C", desc = "Check for updates and show the log (git fetch)" },
{ name = "log", key = "L", desc = "Show recent updates for all plugins" }, { name = "log", key = "L", desc = "Show recent updates for all plugins" },
{ name = "restore", key = "R", desc = "Updates all plugins to the state in the lockfile" }, { name = "restore", key = "R", desc = "Updates all plugins to the state in the lockfile" },
{ name = "help", key = "g?", hide = true, desc = "Toggle this help page" }, { name = "profile", key = "P", desc = "Show detailed profiling", toggle = true },
{ name = "help", key = "g?", hide = true, desc = "Toggle this help page", toggle = true },
{ plugin = true, name = "update", key = "u", desc = "Update this plugin. This will also update the lockfile" }, { plugin = true, name = "update", key = "u", desc = "Update this plugin. This will also update the lockfile" },
{ {
@ -36,11 +37,7 @@ function M.setup()
end end
function M.show(mode) function M.show(mode)
if mode == "help" and M.mode == "help" then
M.mode = nil
else
M.mode = mode or M.mode M.mode = mode or M.mode
end
require("lazy.view.colors").setup() require("lazy.view.colors").setup()
if M._buf and vim.api.nvim_buf_is_valid(M._buf) then if M._buf and vim.api.nvim_buf_is_valid(M._buf) then
@ -171,6 +168,10 @@ function M.show(mode)
Commands.cmd(m.name, { plugin }) Commands.cmd(m.name, { plugin })
end end
else else
if M.mode == m.name and m.toggle then
M.mode = nil
return update()
end
Commands.cmd(m.name) Commands.cmd(m.name)
end end
end, { buffer = buf }) end, { buffer = buf })

View File

@ -60,6 +60,8 @@ function M:update()
if mode == "help" then if mode == "help" then
self:help() self:help()
elseif mode == "profile" then
self:profile()
else else
for _, section in ipairs(Sections) do for _, section in ipairs(Sections) do
self:section(section) self:section(section)
@ -109,7 +111,7 @@ function M:title()
end end
self:nl() self:nl()
if View.mode ~= "help" then if View.mode ~= "help" and View.mode ~= "profile" then
if self.progress.done < self.progress.total then if self.progress.done < self.progress.total then
self:append("Tasks: ", "LazyH2") self:append("Tasks: ", "LazyH2")
self:append(self.progress.done .. "/" .. self.progress.total, "LazyMuted") self:append(self.progress.done .. "/" .. self.progress.total, "LazyMuted")
@ -181,9 +183,14 @@ function M:diagnostic(diag)
table.insert(self._diagnostics, diag) table.insert(self._diagnostics, diag)
end end
---@param plugin LazyPlugin ---@param reason? {[string]:string, time:number}
function M:reason(plugin) ---@param opts? {time_right?:boolean}
local reason = vim.deepcopy(plugin._.loaded or {}) function M:reason(reason, opts)
opts = opts or {}
if not reason then
return
end
reason = vim.deepcopy(reason)
---@type string? ---@type string?
local source = reason.source local source = reason.source
if source then if source then
@ -207,12 +214,16 @@ function M:reason(plugin)
end end
end end
end end
self:append(" " .. math.floor((reason.time or 0) / 1e6 * 100) / 100 .. "ms", "Bold") local time = " " .. math.floor((reason.time or 0) / 1e6 * 100) / 100 .. "ms"
if not opts.time_right then
self:append(time, "Bold")
end
self:append(" ") self:append(" ")
-- self:append(" (", "Conceal") -- self:append(" (", "Conceal")
local first = true local first = true
for key, value in pairs(reason) do for key, value in pairs(reason) do
if key == "require" then if type(key) == "number" then
elseif key == "require" then
-- self:append("require", "@function.builtin") -- self:append("require", "@function.builtin")
-- self:append("(", "@punctuation.bracket") -- self:append("(", "@punctuation.bracket")
-- self:append('"' .. value .. '"', "@string") -- self:append('"' .. value .. '"', "@string")
@ -237,6 +248,9 @@ function M:reason(plugin)
end end
end end
end end
if opts.time_right then
self:append(time, "Bold")
end
-- self:append(")", "Conceal") -- self:append(")", "Conceal")
end end
@ -270,10 +284,14 @@ end
---@param plugin LazyPlugin ---@param plugin LazyPlugin
function M:plugin(plugin) function M:plugin(plugin)
self:append(" - ", "LazySpecial"):append(plugin.name) if plugin._.loaded then
self:append("", "LazySpecial"):append(plugin.name)
else
self:append("", "LazySpecial"):append(plugin.name)
end
local plugin_start = self:row() local plugin_start = self:row()
if plugin._.loaded then if plugin._.loaded then
self:reason(plugin) self:reason(plugin._.loaded)
end end
self:diagnostics(plugin) self:diagnostics(plugin)
self:nl() self:nl()
@ -377,4 +395,32 @@ function M:details(plugin)
self:nl() self:nl()
end end
function M:profile()
self:append("Profile", "LazyH2"):nl():nl()
local symbols = {
"",
"",
"",
"",
}
---@param entry LazyProfile
local function _profile(entry, depth)
local data = type(entry.data) == "string" and { source = entry.data } or entry.data
data.time = entry.time
local symbol = symbols[depth] or symbols[#symbols]
self:append((" "):rep(depth)):append(" " .. symbol, "LazySpecial")
self:reason(data, { time_right = true })
self:nl()
for _, child in ipairs(entry) do
_profile(child, depth + 1)
end
end
for _, entry in ipairs(Util._profiles[1]) do
_profile(entry, 1)
end
end
return M return M