Skip to content

Commit 87c6435

Browse files
committed
Added a checkbox to auto-enable profiling on login, and substantially improved background performance
1 parent 7b6e69e commit 87c6435

2 files changed

Lines changed: 130 additions & 75 deletions

File tree

‎BufferUtil.lua‎

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@ local tRemoveMulti = table.removemulti
44

55
--- @class FP_Buffer
66
local Buffer = {
7+
--- @type FP_BufferContainer[]
78
containers = {},
9+
pendingSquash = false,
10+
curTickIndex = 1,
11+
tickMap = { [1] = GetTime() },
812
};
913
ns.Buffer = Buffer;
1014

1115
local BUCKET_CUTOFF = 2000; -- rather arbitrary number, but interestingly, the lower your fps, the less often actual work will be performed to purge old data ^^
1216

1317
local frame = CreateFrame("Frame");
14-
local doSquash = function() Buffer:Squash(); end;
18+
local doTick = function() Buffer:Tick(); end;
1519
frame:SetScript("OnUpdate", nil);
1620

1721
--- @class FP_BufferContainer
@@ -27,11 +31,23 @@ function Buffer:GetContainer(owner)
2731
return self.containers[owner];
2832
end
2933

34+
function Buffer:Tick()
35+
self.curTickIndex = self.curTickIndex + 1;
36+
self.tickMap[self.curTickIndex] = GetTime();
37+
if not Buffer.pendingSquash then
38+
Buffer.pendingSquash = true;
39+
C_Timer.After(1, function() Buffer:Squash(); end);
40+
end
41+
end
42+
3043
function Buffer:Squash()
44+
self.pendingSquash = false;
3145
frame:SetScript("OnUpdate", nil);
3246
for _, container in pairs(self.containers) do
3347
container:Squash();
3448
end
49+
self.curTickIndex = 1;
50+
self.tickMap = { [1] = GetTime() };
3551
end
3652

3753
function Buffer:Reset()
@@ -42,7 +58,7 @@ end
4258
function BufferContainerMixin:Init()
4359
--- @type FP_BufferSquashedEntry[]
4460
self.entries = {};
45-
--- @type {time: number, mem: number}[]
61+
--- @type {time: number, mem: number, tick: number}[]
4662
self.buffer = {};
4763
--- @type FP_Bucket[]
4864
self.buckets = {};
@@ -51,9 +67,9 @@ function BufferContainerMixin:Init()
5167
end
5268

5369
function BufferContainerMixin:Insert(time, mem)
54-
frame:SetScript("OnUpdate", doSquash);
70+
frame:SetScript("OnUpdate", doTick);
5571
self.pending = true;
56-
tInsert(self.buffer, { time = time, mem = mem});
72+
tInsert(self.buffer, { time = time, mem = mem, tick = Buffer.curTickIndex });
5773
end
5874

5975
function BufferContainerMixin:InitNewBucket()
@@ -141,14 +157,26 @@ end
141157

142158
function BufferContainerMixin:Squash()
143159
if not self.pending then return; end
144-
local squashed = {
145-
totalTime = 0,
146-
worstTime = 0,
147-
totalMem = 0,
148-
worstMem = 0,
149-
entryCount = 0,
150-
};
160+
local lastBucket = self.lastBucket;
161+
local tickIndex = nil;
162+
local squashed = nil;
151163
for _, entry in pairs(self.buffer) do
164+
if entry.tick ~= tickIndex then
165+
tickIndex = entry.tick;
166+
squashed = {
167+
totalTime = 0,
168+
worstTime = 0,
169+
totalMem = 0,
170+
worstMem = 0,
171+
entryCount = 0,
172+
};
173+
174+
local curTickIndex = lastBucket.curTickIndex + 1;
175+
lastBucket.curTickIndex = curTickIndex;
176+
lastBucket.tickMap[curTickIndex] = Buffer.tickMap[tickIndex];
177+
lastBucket.entries[curTickIndex] = squashed;
178+
end
179+
152180
squashed.entryCount = squashed.entryCount + 1;
153181
squashed.totalTime = squashed.totalTime + entry.time;
154182
squashed.totalMem = squashed.totalMem + entry.mem;
@@ -160,12 +188,6 @@ function BufferContainerMixin:Squash()
160188
end
161189
end
162190

163-
local lastBucket = self.lastBucket;
164-
local curTickIndex = lastBucket.curTickIndex + 1;
165-
lastBucket.curTickIndex = curTickIndex;
166-
lastBucket.tickMap[curTickIndex] = GetTime();
167-
lastBucket.entries[curTickIndex] = squashed;
168-
169191
self.buffer = {};
170192
self.pending = false;
171193
end

‎Profiler.lua‎

Lines changed: 91 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ function FP:InitUI()
149149
end
150150
local TIME_FORMAT = function(val) return (val > 0.0005 and whiteColorFormat or greyColorFormat):format(("%.3f"):format(val)) .. msText; end;
151151
local ROUND_TIME_FORMAT = function(val) return (val > 0.0005 and whiteColorFormat or greyColorFormat):format(val) .. msText; end;
152-
local FRACTIONAL_COUNTER_FORMAT = function(val) return (val > 0.0005 and whiteColorFormat or greyColorFormat):format(("%.1f"):format(val)) .. xText; end;
152+
local FRACTIONAL_COUNTER_FORMAT = function(val) return (val > 0.05 and whiteColorFormat or greyColorFormat):format(("%.1f"):format(val)) .. xText; end;
153153
local COUNTER_FORMAT = function(val) return (val > 0.0005 and whiteColorFormat or greyColorFormat):format(math.ceil(val)) .. xText; end;
154154
local RAW_FORMAT = function(val) return val; end;
155155
local PERCENT_FORMAT = function(val)
@@ -319,50 +319,62 @@ function FP:InitUI()
319319
--- @class FP_Display: ButtonFrameTemplate
320320
local display = CreateFrame("Frame", "FunctionProfilerFrame", UIParent, "ButtonFrameTemplate");
321321
FP.Display = display;
322-
local width = 40;
323-
for _, info in pairs(COLUMN_INFO) do
324-
width = width + (info.width - 2)
325-
end
326-
display:SetSize(width, 651);
327-
display:SetPoint("CENTER", 0, 0);
328-
display:SetMovable(true);
329-
display:EnableMouse(true);
330-
display:SetToplevel(true);
331-
display:SetScript("OnShow", function()
332-
display.elapsed = UPDATE_INTERVAL
333-
334-
if continuousUpdate then
335-
display:SetScript("OnUpdate", display.OnUpdate)
322+
do
323+
local width = 40;
324+
for _, info in pairs(COLUMN_INFO) do
325+
width = width + (info.width - 2)
336326
end
337-
end);
338-
display:SetScript("OnHide", function()
339-
display:SetScript("OnUpdate", nil);
340-
end);
341-
display:Hide();
342-
343-
function display:OnUpdate(elapsed)
344-
self.elapsed = (self.elapsed or 0) + elapsed
345-
if self.elapsed >= UPDATE_INTERVAL then
346-
FP:PrepareFilteredData()
347-
348-
local perc = self.ScrollBox:GetScrollPercentage()
349-
self.ScrollBox:Flush()
350-
351-
if FP.dataProvider then
352-
self.ScrollBox:SetDataProvider(FP.dataProvider)
353-
self.ScrollBox:SetScrollPercentage(perc)
327+
display:SetSize(width, 651);
328+
display:SetPoint("CENTER", 0, 0);
329+
display:SetMovable(true);
330+
display:EnableMouse(true);
331+
display:SetToplevel(true);
332+
display:SetScript("OnShow", function()
333+
display.elapsed = UPDATE_INTERVAL
334+
335+
if continuousUpdate then
336+
display:SetScript("OnUpdate", display.OnUpdate)
337+
end
338+
end);
339+
display:SetScript("OnHide", function()
340+
display:SetScript("OnUpdate", nil);
341+
end);
342+
display:Hide();
343+
344+
function display:OnUpdate(elapsed)
345+
self.elapsed = (self.elapsed or 0) + elapsed
346+
if self.elapsed >= UPDATE_INTERVAL then
347+
FP:PrepareFilteredData()
348+
349+
local perc = self.ScrollBox:GetScrollPercentage()
350+
self.ScrollBox:Flush()
351+
352+
if FP.dataProvider then
353+
self.ScrollBox:SetDataProvider(FP.dataProvider)
354+
self.ScrollBox:SetScrollPercentage(perc)
355+
end
356+
357+
self.elapsed = 0
354358
end
359+
end
355360

356-
self.elapsed = 0
357-
end
358-
end
361+
function display:RefreshActiveColumns()
362+
display.activeColumns = {}
363+
for ID, info in pairs(COLUMN_INFO) do
364+
t_insert(display.activeColumns, info)
365+
end
366+
table.sort(display.activeColumns, function(a, b) return a.order < b.order end)
367+
end
359368

360-
ButtonFrameTemplate_HidePortrait(display)
369+
display:RefreshActiveColumns()
361370

362-
display:SetTitle("|cffe03d02Numy:|r Function Profiler")
371+
ButtonFrameTemplate_HidePortrait(display)
363372

364-
display.Inset:SetPoint("TOPLEFT", 8, -86)
365-
display.Inset:SetPoint("BOTTOMRIGHT", -4, 30)
373+
display:SetTitle("|cffe03d02Numy:|r Function Profiler")
374+
375+
display.Inset:SetPoint("TOPLEFT", 8, -86)
376+
display.Inset:SetPoint("BOTTOMRIGHT", -4, 30)
377+
end
366378

367379
local titleBar = CreateFrame("Frame", nil, display, "PanelDragBarTemplate")
368380
display.TitleBar = titleBar
@@ -419,16 +431,6 @@ function FP:InitUI()
419431
end)
420432
end
421433

422-
function display:RefreshActiveColumns()
423-
display.activeColumns = {}
424-
for ID, info in pairs(COLUMN_INFO) do
425-
t_insert(display.activeColumns, info)
426-
end
427-
table.sort(display.activeColumns, function(a, b) return a.order < b.order end)
428-
end
429-
430-
display:RefreshActiveColumns()
431-
432434
--- @class FP_Display.Headers: ColumnDisplayTemplate
433435
local headers = CreateFrame("Button", "$parentHeaders", display, "ColumnDisplayTemplate")
434436
display.Headers = headers;
@@ -838,6 +840,20 @@ function FP:InitUI()
838840
end
839841
end);
840842
end
843+
844+
local autoEnableCheckbox = CreateFrame("CheckButton", "$parentAutoEnableCheckbox", display, "UICheckButtonTemplate");
845+
display.AutoEnableCheckbox = autoEnableCheckbox;
846+
do
847+
autoEnableCheckbox:SetPoint("LEFT", toggleButton, "RIGHT", 15, 0);
848+
autoEnableCheckbox:SetSize(25, 25);
849+
autoEnableCheckbox:SetChecked(FP.db.startEnabled);
850+
851+
autoEnableCheckbox.Text:SetText("Auto-enable on login");
852+
autoEnableCheckbox:SetHitRectInsets(0, -autoEnableCheckbox.Text:GetWidth() - 5, 0, 0);
853+
autoEnableCheckbox:SetScript("OnClick", function(btn)
854+
FP.db.startEnabled = btn:GetChecked();
855+
end);
856+
end
841857
end
842858
end
843859

@@ -987,31 +1003,48 @@ function FP:InitMinimapButton()
9871003
end
9881004
end
9891005

990-
function FP:Init()
1006+
function FP:InitDB()
9911007
_G.FunctionProfilerDB = FunctionProfilerDB or {};
992-
FP.db = FunctionProfilerDB;
1008+
--- @type FP_DB
1009+
self.db = FunctionProfilerDB;
1010+
1011+
--- @class FP_DB
1012+
local defaults = {
1013+
startEnabled = false,
1014+
};
1015+
for k, v in pairs(defaults) do
1016+
if self.db[k] == nil then self.db[k] = v; end
1017+
end
1018+
end
9931019

994-
FP:InitUI();
1020+
function FP:Init()
1021+
self:InitDB();
1022+
self:InitUI();
9951023
EventUtil.ContinueOnAddOnLoaded("BlizzMove", function()
996-
FP:RegisterIntoBlizzMove();
1024+
self:RegisterIntoBlizzMove();
9971025
end);
9981026

999-
FP:InitMinimapButton();
1027+
self:InitMinimapButton();
10001028

10011029
SLASH_NUMY_FUNCTION_PROFILER1 = '/fp';
10021030
SLASH_NUMY_FUNCTION_PROFILER2 = '/nfp';
10031031
SLASH_NUMY_FUNCTION_PROFILER3 = '/functionprofiler';
10041032
SlashCmdList['NUMY_FUNCTION_PROFILER'] = function(message)
1005-
FP:SlashCommand(message);
1033+
self:SlashCommand(message);
10061034
end;
10071035

10081036
-- self profiling.. be careful
10091037
do
1010-
ns.API:WrapInPlace("FunctionProfiler", "FP", FP, "PurgeOldData");
1011-
ns.API:WrapInPlace("FunctionProfiler", "FP", FP, "PrepareFilteredData");
1012-
ns.API:WrapInPlace("FunctionProfiler", "FP", FP, "SortFilteredData");
1038+
ns.API:WrapInPlace("FunctionProfiler", "FP", self, "PurgeOldData");
1039+
ns.API:WrapInPlace("FunctionProfiler", "FP", self, "PrepareFilteredData");
1040+
ns.API:WrapInPlace("FunctionProfiler", "FP", self, "SortFilteredData");
10131041
ns.API:WrapInPlace("FunctionProfiler", "Buffer", ns.Buffer, "Squash");
10141042
end
1043+
1044+
if self.db.startEnabled then
1045+
ns.API:EnableLogging();
1046+
self:Print("profiling on start-up has been enabled. Don't forget to turn it off if it starts to affect your performance.")
1047+
end
10151048
end
10161049

10171050
FP:Init();

0 commit comments

Comments
 (0)