Skip to content

Commit 42e7e7b

Browse files
committed
Implemented percentage columns, such as Recent % and Total %
1 parent 9b11417 commit 42e7e7b

File tree

1 file changed

+130
-11
lines changed

1 file changed

+130
-11
lines changed

AddonProfiler.lua

Lines changed: 130 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ local thisAddonName = ...
33
local s_trim = string.trim
44
local t_insert = table.insert
55
local t_removemulti = table.removemulti
6-
local t_remove = table.remove
76
local t_wipe = table.wipe
87
local pairs = pairs
98
local GetTime = GetTime
@@ -79,10 +78,8 @@ end
7978
--- collect all available data
8079
local ACTIVE_MODE = 'active';
8180
--- collect only total and peak data - disables history range
82-
--- @todo mostly implemented, but no toggle yet
8381
local PERFORMANCE_MODE = 'performance';
8482
--- collect no data at all, just reset the spike ms counters on reset - disables history range, and maybe show different columns?
85-
--- @todo not yet implemented
8683
local PASSIVE_MODE = 'passive';
8784

8885
--- @type table<string, { title: string, notes: string, loaded: boolean }>
@@ -148,10 +145,15 @@ end
148145
local HEADER_IDS = {
149146
addonTitle = "addonTitle",
150147
encounterAvgMs = "encounterAvgMs",
148+
overallEncounterAvgPercent = "overallEncounterAvgPercent",
151149
peakTimeMs = "peakTimeMs",
150+
overallPeakTimePercent = "overallPeakTimePercent",
152151
recentMs = "recentMs",
152+
overallRecentPercent = "overallRecentPercent",
153153
averageMs = "averageMs",
154154
totalMs = "totalMs",
155+
overallTotalPercent = "overallTotalPercent",
156+
applicationTotalPercent = "applicationTotalPercent",
155157
["overCount-1"] = "overCount-1",
156158
["overCount-5"] = "overCount-5",
157159
["overCount-10"] = "overCount-10",
@@ -171,10 +173,15 @@ function NAP:InitDB()
171173
local defaultShownColumns = {
172174
[HEADER_IDS.addonTitle] = true,
173175
[HEADER_IDS.encounterAvgMs] = true,
176+
[HEADER_IDS.overallEncounterAvgPercent] = false,
174177
[HEADER_IDS.peakTimeMs] = true,
178+
[HEADER_IDS.overallPeakTimePercent] = false,
175179
[HEADER_IDS.recentMs] = false,
180+
[HEADER_IDS.overallRecentPercent] = false,
176181
[HEADER_IDS.averageMs] = true,
177182
[HEADER_IDS.totalMs] = true,
183+
[HEADER_IDS.overallTotalPercent] = true,
184+
[HEADER_IDS.applicationTotalPercent] = true,
178185
[HEADER_IDS['overCount-1']] = true,
179186
[HEADER_IDS['overCount-5']] = true,
180187
[HEADER_IDS['overCount-10']] = true,
@@ -416,10 +423,15 @@ end
416423
---@field addonTitle string
417424
---@field addonNotes string
418425
---@field peakTime number
426+
---@field overallPeakTime number
419427
---@field encounterAvg number
428+
---@field overallEncounterAvg number
420429
---@field recentMs number
430+
---@field overallRecentMs number
421431
---@field averageMs number
422432
---@field totalMs number
433+
---@field overallTotalMs number
434+
---@field applicationTotalMs number
423435
---@field numberOfTicks number
424436
---@field over1Ms number
425437
---@field over5Ms number
@@ -429,6 +441,7 @@ end
429441
---@field over500Ms number
430442
---@field over1000Ms number
431443
---@field overMsSum number
444+
-- 11.1 will likely allow adding applicationPeakTime, applicationEncounterAvg, applicationRecentMs
432445

433446
--- @param forceUpdate boolean
434447
--- @return table<NAP_Bucket, number>? bucketsWithinHistory
@@ -462,11 +475,12 @@ function NAP:PrepareFilteredData(forceUpdate)
462475
end
463476
end
464477
end
478+
local overallStats = self:GetElelementDataForAddon(TOTAL_ADDON_METRICS_KEY, nil, withinHistory);
465479

466480
for addonName in pairs(self.loadedAddons) do
467481
local info = self.addons[addonName];
468482
if info.title:lower():match(self.curMatch) then
469-
t_insert(self.filteredData, self:GetElelementDataForAddon(addonName, info, withinHistory));
483+
t_insert(self.filteredData, self:GetElelementDataForAddon(addonName, info, withinHistory, overallStats));
470484
end
471485
end
472486

@@ -479,20 +493,22 @@ function NAP:PrepareFilteredData(forceUpdate)
479493
end
480494

481495
---@param addonName string
482-
---@param info { title: string, notes: string, loaded: boolean }
496+
---@param info nil|{ title: string, notes: string, loaded: boolean }
483497
---@param bucketsWithinHistory table<NAP_Bucket, number>
498+
---@param overallStats NAP_ElementData?
484499
---@return NAP_ElementData
485-
function NAP:GetElelementDataForAddon(addonName, info, bucketsWithinHistory)
500+
function NAP:GetElelementDataForAddon(addonName, info, bucketsWithinHistory, overallStats)
486501
---@type NAP_ElementData
487502
---@diagnostic disable-next-line: missing-fields
488503
local data = {
489504
addonName = addonName,
490-
addonTitle = info.title,
491-
addonNotes = info.notes,
505+
addonTitle = info and info.title or '',
506+
addonNotes = info and info.notes or '',
492507
peakTime = 0,
493508
averageMs = 0,
494509
totalMs = 0,
495510
numberOfTicks = 0,
511+
applicationTotalMs = 0,
496512
};
497513
if TOTAL_ADDON_METRICS_KEY == addonName then
498514
data.encounterAvg = C_AddOnProfiler_GetOverallMetric(Enum_AddOnProfilerMetric_EncounterAverageTime);
@@ -504,7 +520,9 @@ function NAP:GetElelementDataForAddon(addonName, info, bucketsWithinHistory)
504520
for _, ms in pairs(msOptions) do
505521
data[msOptionFieldMap[ms]] = 0;
506522
end
523+
local now = self.frozenAt or GetTime();
507524
if INFINITE_HISTORY == self:GetActiveHistoryRange() then
525+
data.applicationTotalMs = (now - self.resetTime) * 1000;
508526
local currentMetrics = self.frozenMetrics and self.frozenMetrics[addonName] or self:GetCurrentMsSpikeMetrics(addonName);
509527
for ms in pairs(msMetricMap) do
510528
local currentMetric = currentMetrics[ms] or 0;
@@ -516,8 +534,16 @@ function NAP:GetElelementDataForAddon(addonName, info, bucketsWithinHistory)
516534
data.totalMs = self.totalMs[addonName];
517535
data.numberOfTicks = self.tickNumber - self.loadedAtTick[addonName];
518536
else
537+
local firstTickTime = now;
538+
local lastTickTime = 0;
519539
for bucket, startingTickIndex in pairs(bucketsWithinHistory) do
520540
data.numberOfTicks = data.numberOfTicks + ((bucket.curTickIndex - startingTickIndex) + 1);
541+
if bucket.tickMap[startingTickIndex] < firstTickTime then
542+
firstTickTime = bucket.tickMap[startingTickIndex];
543+
end
544+
if bucket.tickMap[bucket.curTickIndex] > lastTickTime then
545+
lastTickTime = bucket.tickMap[bucket.curTickIndex];
546+
end
521547
for tickIndex = startingTickIndex, bucket.curTickIndex do
522548
local tickMs = bucket.lastTick[addonName] and bucket.lastTick[addonName][tickIndex];
523549
if tickMs and tickMs > 0 then
@@ -550,6 +576,8 @@ function NAP:GetElelementDataForAddon(addonName, info, bucketsWithinHistory)
550576
end
551577
end
552578
end
579+
580+
data.applicationTotalMs = (lastTickTime - firstTickTime) * 1000;
553581
end
554582
data.averageMs = data.numberOfTicks > 0 and (data.totalMs / data.numberOfTicks) or 0; -- let's not divide by 0 :)
555583

@@ -570,6 +598,18 @@ function NAP:GetElelementDataForAddon(addonName, info, bucketsWithinHistory)
570598
previousGroupCount = count;
571599
end
572600

601+
if TOTAL_ADDON_METRICS_KEY == addonName then
602+
data.overallPeakTime = data.peakTime;
603+
data.overallEncounterAvg = data.encounterAvg;
604+
data.overallRecentMs = data.recentMs;
605+
data.overallTotalMs = data.totalMs;
606+
elseif overallStats then
607+
data.overallPeakTime = overallStats.peakTime;
608+
data.overallEncounterAvg = overallStats.encounterAvg;
609+
data.overallRecentMs = overallStats.recentMs;
610+
data.overallTotalMs = overallStats.totalMs;
611+
end
612+
573613
return data;
574614
end
575615

@@ -590,9 +630,18 @@ function NAP:InitUI()
590630
local ROUND_TIME_FORMAT = function(val) return (val > 0 and whiteColorFormat or greyColorFormat):format(val) .. msText; end;
591631
local COUNTER_FORMAT = function(val) return (val > 0 and whiteColorFormat or greyColorFormat):format(val) .. xText; end;
592632
local RAW_FORMAT = function(val) return val; end;
633+
local PERCENT_FORMAT = function(val)
634+
local color = val > 0.00005 and whiteColorFormat or greyColorFormat;
635+
636+
return val >= 1 and color:format("100.00%") or color:format(("%.2f%%"):format(val * 100));
637+
end;
593638

594639
local COLUMN_INFO = {};
595640
do
641+
local totalAddonsText = NORMAL_FONT_COLOR:WrapTextInColorCode("Total Addons");
642+
local applicationText = NORMAL_FONT_COLOR:WrapTextInColorCode("Application");
643+
local applicationShortText = NORMAL_FONT_COLOR:WrapTextInColorCode("App");
644+
596645
local Inf = math.huge
597646
local function makeSortMethods(key)
598647
return {
@@ -640,7 +689,21 @@ function NAP:InitUI()
640689
width = 96,
641690
textFormatter = TIME_FORMAT,
642691
textKey = "encounterAvg",
643-
tooltip = "Average CPU time spent per frame during a boss encounter. Ignores the History Range",
692+
tooltip = "Average CPU time spent per frame during a boss encounter. Ignores the History Range.",
693+
sortMethods = makeSortMethods("encounterAvg"),
694+
};
695+
COLUMN_INFO[HEADER_IDS.overallEncounterAvgPercent] = {
696+
ID = HEADER_IDS.overallEncounterAvgPercent,
697+
order = counter(),
698+
availableInPassiveMode = true,
699+
title = "Boss Avg %",
700+
width = 96,
701+
textFormatter = PERCENT_FORMAT,
702+
---@param data NAP_ElementData
703+
textFunc = function(data)
704+
return data.overallEncounterAvg > 0 and (data.encounterAvg / data.overallEncounterAvg) or 0;
705+
end,
706+
tooltip = "Percentage of " .. totalAddonsText .. " CPU time spent per frame during a boss encounter. Ignores the History Range.",
644707
sortMethods = makeSortMethods("encounterAvg"),
645708
};
646709
COLUMN_INFO[HEADER_IDS.peakTimeMs] = {
@@ -654,6 +717,20 @@ function NAP:InitUI()
654717
tooltip = "Biggest spike in ms, within the History Range.",
655718
sortMethods = makeSortMethods("peakTime"),
656719
};
720+
COLUMN_INFO[HEADER_IDS.overallPeakTimePercent] = {
721+
ID = HEADER_IDS.overallPeakTimePercent,
722+
order = counter(),
723+
availableInPassiveMode = true,
724+
title = "Peak %",
725+
width = 96,
726+
textFormatter = PERCENT_FORMAT,
727+
---@param data NAP_ElementData
728+
textFunc = function(data)
729+
return data.overallPeakTime > 0 and (data.peakTime / data.overallPeakTime) or 0;
730+
end,
731+
tooltip = "Percentage of " .. totalAddonsText .. " biggest spike in ms, within the History Range.",
732+
sortMethods = makeSortMethods("peakTime"),
733+
};
657734
COLUMN_INFO[HEADER_IDS.recentMs] = {
658735
ID = HEADER_IDS.recentMs,
659736
order = counter(),
@@ -665,6 +742,20 @@ function NAP:InitUI()
665742
tooltip = "Average CPU time spent in the last 60 frames. Ignores the History Range",
666743
sortMethods = makeSortMethods("recentMs"),
667744
};
745+
COLUMN_INFO[HEADER_IDS.overallRecentPercent] = {
746+
ID = HEADER_IDS.overallRecentPercent,
747+
order = counter(),
748+
availableInPassiveMode = true,
749+
title = "Recent %",
750+
width = 96,
751+
textFormatter = PERCENT_FORMAT,
752+
---@param data NAP_ElementData
753+
textFunc = function(data)
754+
return data.overallRecentMs > 0 and (data.recentMs / data.overallRecentMs) or 0;
755+
end,
756+
tooltip = "Percentage of " .. totalAddonsText .. " CPU time spent in the last 60 frames. Ignores the History Range.",
757+
sortMethods = makeSortMethods("recentMs"),
758+
};
668759
COLUMN_INFO[HEADER_IDS.averageMs] = {
669760
ID = HEADER_IDS.averageMs,
670761
order = counter(),
@@ -685,6 +776,32 @@ function NAP:InitUI()
685776
tooltip = "Total CPU time spent, within the History Range.",
686777
sortMethods = makeSortMethods("totalMs"),
687778
};
779+
COLUMN_INFO[HEADER_IDS.overallTotalPercent] = {
780+
ID = HEADER_IDS.overallTotalPercent,
781+
order = counter(),
782+
title = "Total %",
783+
width = 96,
784+
textFormatter = PERCENT_FORMAT,
785+
---@param data NAP_ElementData
786+
textFunc = function(data)
787+
return data.overallTotalMs > 0 and (data.totalMs / data.overallTotalMs) or 0;
788+
end,
789+
tooltip = "Percentage of " .. totalAddonsText .. " CPU time spent, within the History Range.",
790+
sortMethods = makeSortMethods("totalMs"),
791+
};
792+
COLUMN_INFO[HEADER_IDS.applicationTotalPercent] = {
793+
ID = HEADER_IDS.applicationTotalPercent,
794+
order = counter(),
795+
title = "Total % of " .. applicationShortText,
796+
width = 96,
797+
textFormatter = PERCENT_FORMAT,
798+
---@param data NAP_ElementData
799+
textFunc = function(data)
800+
return data.applicationTotalMs > 0 and (data.totalMs / data.applicationTotalMs) or 0;
801+
end,
802+
tooltip = "CPU time spent, as a percentage of the total " .. applicationText .. " CPU time. This includes default UI, graphics, etc.",
803+
sortMethods = makeSortMethods("totalMs"),
804+
};
688805
for _, ms in ipairs(msOptions) do
689806
COLUMN_INFO[HEADER_IDS["overCount-" .. ms]] = {
690807
ID = HEADER_IDS["overCount-" .. ms],
@@ -1159,7 +1276,8 @@ function NAP:InitUI()
11591276
self:UpdateColumns()
11601277
for columnText in self.columnPool:EnumerateActive() do
11611278
local column = columnText.column
1162-
columnText:SetText(column.textFormatter(self.data[column.textKey]))
1279+
local value = column.textFunc and column.textFunc(self.data) or self.data[column.textKey]
1280+
columnText:SetText(column.textFormatter(value))
11631281
end
11641282
end
11651283
end
@@ -1179,7 +1297,8 @@ function NAP:InitUI()
11791297
row:UpdateColumns()
11801298
for columnText in row.columnPool:EnumerateActive() do
11811299
local column = columnText.column
1182-
columnText:SetText(column.textFormatter(data[column.textKey]))
1300+
local value = column.textFunc and column.textFunc(data) or data[column.textKey]
1301+
columnText:SetText(column.textFormatter(value))
11831302
end
11841303
end)
11851304

0 commit comments

Comments
 (0)