profiler
This commit is contained in:
parent
6a5c2fc951
commit
bf09a8844a
1 changed files with 59 additions and 0 deletions
59
profiler.lua
Normal file
59
profiler.lua
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
-- Developer-only CPU sampler. It is inert until F9 is pressed.
|
||||||
|
--
|
||||||
|
-- On stop it writes `chroma-solstice.folded` in LÖVE's save directory. The
|
||||||
|
-- file uses Brendan Gregg's folded-stack format and can be given directly to
|
||||||
|
-- FlameGraph's flamegraph.pl.
|
||||||
|
PerfProfiler = {
|
||||||
|
active = false,
|
||||||
|
samples = {},
|
||||||
|
status = "F9: start CPU profile",
|
||||||
|
}
|
||||||
|
|
||||||
|
local ok, profile = pcall(require, "jit.profile")
|
||||||
|
PerfProfiler.available = ok
|
||||||
|
if not ok then
|
||||||
|
PerfProfiler.status = "LuaJIT sampler unavailable"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sample(thread, count, vmstate)
|
||||||
|
-- Negative depth produces caller -> callee order, which is what folded
|
||||||
|
-- flamegraphs expect. Function-level samples keep the output compact.
|
||||||
|
local stack = profile.dumpstack(thread, "pF;", -64):gsub(";$", "")
|
||||||
|
if stack ~= "" then
|
||||||
|
PerfProfiler.samples[stack] = (PerfProfiler.samples[stack] or 0) + count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function PerfProfiler:toggle()
|
||||||
|
if not self.available then return false end
|
||||||
|
if not self.active then
|
||||||
|
self.samples = {}
|
||||||
|
profile.start("fi2", sample)
|
||||||
|
self.active = true
|
||||||
|
self.status = "CPU profile recording (F9 to write)"
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
profile.stop()
|
||||||
|
self.active = false
|
||||||
|
local lines, sampleCount = {}, 0
|
||||||
|
for stack, count in pairs(self.samples) do
|
||||||
|
table.insert(lines, stack .. " " .. count)
|
||||||
|
sampleCount = sampleCount + count
|
||||||
|
end
|
||||||
|
table.sort(lines)
|
||||||
|
local path = "chroma-solstice.folded"
|
||||||
|
local saved = love.filesystem.write(path, table.concat(lines, "\n") .. "\n")
|
||||||
|
local directory = love.filesystem.getSaveDirectory()
|
||||||
|
self.status = saved and ("CPU profile saved (" .. sampleCount .. " samples); see terminal")
|
||||||
|
or "Could not write CPU profile"
|
||||||
|
if saved then print("CPU profile: " .. directory .. "/" .. path) else print(self.status) end
|
||||||
|
return saved
|
||||||
|
end
|
||||||
|
|
||||||
|
function PerfProfiler:draw()
|
||||||
|
if not self.active and self.status == "F9: start CPU profile" then return end
|
||||||
|
love.graphics.setColor(self.active and 1 or 0.6, self.active and 0.75 or 1, self.active and 0.2 or 0.6, 1)
|
||||||
|
love.graphics.print(self.active and "PROFILING: F9 to save flamegraph data" or self.status, 10, 28)
|
||||||
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
end
|
||||||
Loading…
Add table
Add a link
Reference in a new issue