Rework profiler for 10.1.0

Since GetFunctionCPUUsage was removed in 10.1.0 the entire profler
stopped working. This has been replaced by wrapping the functions in a
closure that runs GetTimePreciseSec before and after and keeps track of
the total runtime per function.
This commit is contained in:
2023-07-27 13:18:29 +02:00
parent b201ef789a
commit 877560cb58

View File

@@ -26,56 +26,115 @@ local Printf = Commander.Printf
local types = omi.GetModule("types")
local data = {}
local startTime
local stopTime
local functionTimers = {}
local functionNames = {}
-- Permanently wrap all functions to do profiling
local function EnableFunctionProfiler()
if #functionTimers ~= 0 then
return
end
local GetTimePreciseSec = GetTimePreciseSec
local counter = 1
for typeName, T in pairs(types) do
if type(T) == "table" then
PrintLn("Type:", typeName, T)
for fnName, fn in pairs(T) do
if type(fn) == "function" then
local fnIdx = counter
counter = counter + 1
local name = string.format("%s:%s", typeName, fnName)
functionTimers[fnIdx] = 0
functionNames[fnIdx] = name
local wrapped = function(...)
local start = GetTimePreciseSec()
local a, b, c, d, e, f, g, h = fn(...)
local elapsed = GetTimePreciseSec() - start
functionTimers[fnIdx] = functionTimers[fnIdx] + elapsed
return a, b, c, d, e, f, g, h
end
T[fnName] = wrapped
end
end
end
end
end
-- Set all function timers back to 0
local function ResetFunctionProfiler()
for i, _ in ipairs(functionTimers) do
functionTimers[i] = 0
end
end
Commander.RegisterCommand("omi-pstart", {
description = "Start/reset the OmicronFrames profiler",
command = function()
local profiler = C_CVar.GetCVar("scriptProfile")
if profiler ~= "1" then
PrintLn("scriptProfiler is off")
PrintLn("set it to on with `/console scriptProfile 1`, then reload the UI.")
PrintLn("OmicronFrames: start profiling")
EnableFunctionProfiler()
ResetFunctionProfiler()
startTime = GetTimePreciseSec()
stopTime = nil
if profiler == "1" then
ResetCPUUsage()
else
PrintLn("WoW scriptProfiler is off. Addon totals will not be shown,")
PrintLn("only individual functions.The profiler will not show total")
PrintLn("addon time, only function profiler.")
PrintLn("")
PrintLn("To enable the script profiler run `/console scriptProfile 1`, then reload the UI.")
return
end
PrintLn("OmicronFrames: start profiling")
ResetCPUUsage()
end
})
Commander.RegisterCommand("omi-pstop", {
description = "Stop the OmicronFrames profiler",
command = function()
if not startTime then
PrintLn("Profiling not started. Run omi-pstart first.")
return
end
PrintLn("OmicronFrames: stop profiling")
local profiler = C_CVar.GetCVar("scriptProfile") == "1"
data = {}
stopTime = GetTimePreciseSec()
if profiler then
UpdateAddOnCPUUsage()
local total = GetAddOnCPUUsage(addonName)
data = {{
table.insert(data, {
name = "Total OmicronFrames time",
time = total,
pct = 1.0
}}
for typeName, T in pairs(types) do
if type(T) == "table" then
for fnName, fn in pairs(T) do
if type(fn) == "function" then
local time = GetFunctionCPUUsage(fn, true)
table.insert(data, {
name = string.format("%s:%s", typeName, fnName),
time = time,
pct = time/total
})
end
for i, time in ipairs(functionTimers) do
local name = functionNames[i]
table.insert(data, {
name = name,
time = time * 1000,
})
end
end
end
table.sort(data, function(a, b) return a.time > b.time end)
table.sort(data, function(a, b) return a.time < b.time end)
end,
})
Commander.RegisterCommand("omi-pprint", {
description = "Print the collected OmicronFrames profiling data",
command = function()
if not stopTime then
PrintLn("Profiling data not collected yet. Run omi-pstop first.")
return
end
local top = data[#data].time
local total = stopTime - startTime
for _, item in ipairs(data) do
Printf("% 5.1f%% % 5fms %s\n", item.pct*100, item.time, item.name)
local time = item.time
local pct = time / top * 100
local ms_per_sec = time / total
Printf("% 6.1f%% % 7.2fms %7.2fms/s %s\n", pct, time, ms_per_sec, item.name)
end
end
})