refactor: move all dashboard tracing to debug

This commit is contained in:
Folke Lemaitre 2024-11-19 14:55:04 +01:00
parent 9c0d2e2e93
commit 143c244346
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
2 changed files with 79 additions and 55 deletions

View file

@ -201,39 +201,20 @@ local D = {}
function M.open(opts)
local self = setmetatable({}, { __index = D })
self.opts = Snacks.config.get("dashboard", defaults, opts) --[[@as snacks.dashboard.Opts]]
self:trace("buf/win")
self.buf = self.opts.buf or vim.api.nvim_create_buf(false, true)
self.win = self.opts.win or Snacks.win({ style = "dashboard", buf = self.buf, enter = true }).win --[[@as number]]
self:trace() -- buf/win
self:trace("dashboard")
self:trace("init")
self:init()
self:trace() -- init
self:update()
self:trace() -- dashboard
if self.opts.debug then
Snacks.debug.stats({ min = 0.2 })
end
self:fire("Opened")
return self
end
---@param name? string
function D:trace(name)
return self.opts.debug and Snacks.debug.trace(name)
return self.opts.debug and Snacks.debug.trace(name and ("dashboard:" .. name) or nil)
end
function D:init()
if self.opts.debug then -- track initial load of icon provider
local icon = M.icon
M.icon = function(...)
self:trace("icon-provider")
local ret = icon(...)
self:trace()
M.icon = icon
return ret
end
end
vim.api.nvim_win_set_buf(self.win, self.buf)
vim.o.ei = "all"
Snacks.util.wo(self.win, Snacks.config.styles.dashboard.wo)
@ -469,7 +450,7 @@ function D:resolve(item, results, parent)
table.insert(results, { title = item.title, icon = item.icon, pane = item.pane })
end
if item.section then -- add section items
self:trace(item.section)
self:trace("resolve." .. item.section)
local items = M.sections[item.section](item) ---@type snacks.dashboard.Section?
self:resolve(items, results, item)
self:trace()
@ -505,9 +486,7 @@ function D:padding(item)
end
function D:fire(event)
self:trace(event)
vim.api.nvim_exec_autocmds("User", { pattern = "SnacksDashboard" .. event, modeline = false })
self:trace()
end
function D:on(event, cb)
@ -549,7 +528,6 @@ end
-- Layout in panes
function D:layout()
self:trace("layout")
local max_panes =
math.max(1, math.floor((self._size.width + self.opts.pane_gap) / (self.opts.width + self.opts.pane_gap)))
self.panes = {} ---@type snacks.dashboard.Item[][]
@ -562,17 +540,14 @@ function D:layout()
for p = 1, math.max(unpack(vim.tbl_keys(self.panes))) or 1 do
self.panes[p] = self.panes[p] or {}
end
self:trace()
end
-- Format and render the dashboard
function D:render()
self:trace("render")
-- horizontal position
self.col = self.opts.col
or math.floor(self._size.width - (self.opts.width * #self.panes + self.opts.pane_gap * (#self.panes - 1))) / 2
self:trace("format")
self.lines = {} ---@type string[]
local extmarks = {} ---@type {row:number, col:number, opts:vim.api.keyset.set_extmark}[]
for p, pane in ipairs(self.panes) do
@ -605,7 +580,6 @@ function D:render()
end
end
end
self:trace() -- format
-- vertical position
self.row = self.opts.row or math.max(math.floor((self._size.height - #self.lines) / 2), 0)
@ -623,7 +597,11 @@ function D:render()
end
end
self:trace("lines/extmarks")
self:render_buf(extmarks)
end
---@param extmarks {row:number, col:number, opts:vim.api.keyset.set_extmark}[]
function D:render_buf(extmarks)
-- set lines
vim.bo[self.buf].modifiable = true
vim.api.nvim_buf_set_lines(self.buf, 0, -1, false, self.lines)
@ -634,12 +612,9 @@ function D:render()
for _, extmark in ipairs(extmarks) do
vim.api.nvim_buf_set_extmark(self.buf, M.ns, extmark.row + self.row, extmark.col, extmark.opts)
end
self:trace() -- lines/extmarks
self:trace() -- render
end
function D:keys()
self:trace("keys")
local autokeys = self.opts.autokeys:gsub("[hjklq]", "")
for _, item in ipairs(self.items) do
if item.key and not item.autokey then
@ -656,18 +631,13 @@ function D:keys()
end, { buffer = self.buf, nowait = not item.autokey, desc = "Dashboard action" })
end
end
self:trace()
end
function D:update()
self:trace("update")
self:fire("UpdatePre")
self._size = self:size()
self:trace("items")
self.items = self:resolve(self.opts.sections)
self:trace() -- items
self:layout()
self:keys()
@ -701,7 +671,6 @@ function D:update()
end,
})
self:fire("UpdatePost")
self:trace() -- update
end
-- Get an icon
@ -1050,6 +1019,11 @@ function M.setup()
end
M.status.opened = true
if Snacks.config.dashboard.debug then
Snacks.debug.tracemod("dashboard", M)
Snacks.debug.tracemod("dashboard", D, ":")
end
local options = { showtabline = vim.o.showtabline, laststatus = vim.o.laststatus }
vim.o.showtabline, vim.o.laststatus = 0, 0
M.open({ buf = buf, win = wins[1] }):on("Closed", function()
@ -1059,6 +1033,10 @@ function M.setup()
end
end
end)
if Snacks.config.dashboard.debug then
Snacks.debug.stats({ min = 0.2 })
end
end
function M.health()

View file

@ -94,9 +94,10 @@ function M.log(...)
end
---@alias snacks.debug.Trace {name: string, time: number, [number]:snacks.debug.Trace}
---@alias snacks.debug.Stat {name:string, time:number, count?:number, depth?:number}
---@type snacks.debug.Trace[]
M._traces = { { name = "snacks" } }
M._traces = { { name = "__TOP__", time = 0 } }
---@param name string?
function M.trace(name)
@ -112,25 +113,70 @@ function M.trace(name)
end
end
---@param opts? {min?: number}
function M.stats(opts)
opts = opts or {}
local lines = {}
---@param stat snacks.debug.Trace
---@param level number
local function collect(stat, level)
for _, entry in ipairs(stat) do
local ms = math.floor(entry.time / 1e4) / 1e2
if ms >= (opts.min or 0) then
table.insert(lines, ("%s- `%s`: **%.2f**ms"):format((" "):rep(level), entry.name, entry.time / 1e6))
if entry[1] then
collect(entry, level + 1)
end
---@param modname string
---@param mod? table
---@param suffix? string
function M.tracemod(modname, mod, suffix)
mod = mod or require(modname)
suffix = suffix or "."
for k, v in pairs(mod) do
if type(v) == "function" and k ~= "trace" then
mod[k] = function(...)
M.trace(modname .. suffix .. k)
local ok, ret = pcall(v, ...)
M.trace()
return ok == false and error(ret) or ret
end
end
end
collect(M._traces[1], 0)
Snacks.notify.warn(lines, { title = "Traces" })
end
---@param opts? {min?: number, show?:boolean}
---@return {summary:table<string, snacks.debug.Stat>, trace:snacks.debug.Stat[], traces:snacks.debug.Trace[]}
function M.stats(opts)
opts = opts or {}
local stack, lines, trace = {}, {}, {} ---@type string[], string[], snacks.debug.Stat[]
local summary = {} ---@type table<string, snacks.debug.Stat>
---@param stat snacks.debug.Trace
local function collect(stat)
if #stack > 0 then
local recursive = vim.list_contains(stack, stat.name)
summary[stat.name] = summary[stat.name] or { time = 0, count = 0, name = stat.name }
summary[stat.name].time = summary[stat.name].time + (recursive and 0 or stat.time)
summary[stat.name].count = summary[stat.name].count + 1
table.insert(trace, { name = stat.name, time = stat.time or 0, depth = #stack - 1 })
end
table.insert(stack, stat.name)
for _, entry in ipairs(stat) do
collect(entry)
end
table.remove(stack)
end
collect(M._traces[1])
---@param entries snacks.debug.Stat[]
local function add(entries)
for _, stat in ipairs(entries) do
local ms = math.floor(stat.time / 1e4) / 1e2
if ms >= (opts.min or 0) then
local line = ("%s- `%s`: **%.2f**ms"):format((" "):rep(stat.depth or 0), stat.name, ms)
table.insert(lines, line .. (stat.count and (" ([%d])"):format(stat.count) or ""))
end
end
end
if opts.show ~= false then
lines[#lines + 1] = "# Summary"
summary = vim.tbl_values(summary)
table.sort(summary, function(a, b)
return a.time > b.time
end)
add(summary)
lines[#lines + 1] = "\n# Trace"
add(trace)
Snacks.notify.warn(lines, { title = "Traces" })
end
return { summary = summary, trace = trace, tree = M._traces }
end
return M