perf: optimize CPU and memory usage via boolean state tracking, event filtering, and per-character SavedVariables.

This commit is contained in:
Bluewhale1337
2026-07-20 23:22:15 +02:00
parent 441a45150f
commit 85ad55c1cb
6 changed files with 25 additions and 35 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
## Version: 1.5 ## Version: 1.5
## Author: Bluewhale ## Author: Bluewhale
## Notes: Adds panel with skinable bars for healing and decursive ## Notes: Adds panel with skinable bars for healing and decursive
## SavedVariables: HealBot_Config ## SavedVariablesPerCharacter: HealBot_Config
..\..\FrameXML\Fonts.xml ..\..\FrameXML\Fonts.xml
..\..\FrameXML\OptionsFrameTemplates.xml ..\..\FrameXML\OptionsFrameTemplates.xml
..\..\FrameXML\UIPanelTemplates.xml ..\..\FrameXML\UIPanelTemplates.xml
+1 -1
View File
@@ -149,7 +149,7 @@ function HealBot_OnEvent_UnitAura(this, unit)
iconCount = iconCount + 1 iconCount = iconCount + 1
HealBot_UnitIcons[unit][iconCount] = debuff HealBot_UnitIcons[unit][iconCount] = debuff
end end
if HealBot_CDCInc[UnitClass(unit)] == 1 and HealBot_DebuffWatch[debuff_type] == "YES" then if HealBot_CDCInc[UnitClass(unit)] == 1 and HealBot_DebuffWatch[debuff_type] then
HealBot_UnitDebuff[unit] = debuff_type HealBot_UnitDebuff[unit] = debuff_type
DebuffType = debuff_type; DebuffType = debuff_type;
if HealBot_DebuffPriority[debuff_type] then if HealBot_DebuffPriority[debuff_type] then
+15 -29
View File
@@ -43,17 +43,20 @@ end
function HealBot_OnUpdate(this, arg1) function HealBot_OnUpdate(this, arg1)
if HealBot_Action_TooltipUnit and HealBot_Tooltip:IsVisible() then if HealBot_Action_TooltipUnit and HealBot_Tooltip:IsVisible() then
local currentModState = "" local s = IsShiftKeyDown() and true or false
if IsShiftKeyDown() then currentModState = currentModState .. "S" end local c = IsControlKeyDown() and true or false
if IsControlKeyDown() then currentModState = currentModState .. "C" end local a = IsAltKeyDown() and true or false
if IsAltKeyDown() then currentModState = currentModState .. "A" end
if HealBot_LastModState ~= currentModState then if HealBot_LastModS ~= s or HealBot_LastModC ~= c or HealBot_LastModA ~= a then
HealBot_LastModState = currentModState HealBot_LastModS = s
HealBot_LastModC = c
HealBot_LastModA = a
HealBot_Action_RefreshTooltip(HealBot_Action_TooltipUnit) HealBot_Action_RefreshTooltip(HealBot_Action_TooltipUnit)
end end
else else
HealBot_LastModState = "" HealBot_LastModS = false
HealBot_LastModC = false
HealBot_LastModA = false
end end
if HealBot_TargetRestorePending then if HealBot_TargetRestorePending then
@@ -131,6 +134,7 @@ local HealBot_EventHandlers = {
HealBot_OnEvent_UnitHealth(this, arg1) HealBot_OnEvent_UnitHealth(this, arg1)
end, end,
["UNIT_MANA"] = function(this, arg1) ["UNIT_MANA"] = function(this, arg1)
if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1) HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end end
@@ -138,6 +142,7 @@ local HealBot_EventHandlers = {
HealBot_Action_RefreshButtons(arg1); HealBot_Action_RefreshButtons(arg1);
end, end,
["UNIT_RAGE"] = function(this, arg1) ["UNIT_RAGE"] = function(this, arg1)
if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1) HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end end
@@ -145,6 +150,7 @@ local HealBot_EventHandlers = {
HealBot_Action_RefreshButtons(arg1); HealBot_Action_RefreshButtons(arg1);
end, end,
["UNIT_ENERGY"] = function(this, arg1) ["UNIT_ENERGY"] = function(this, arg1)
if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1) HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end end
@@ -152,6 +158,7 @@ local HealBot_EventHandlers = {
HealBot_Action_RefreshButtons(arg1); HealBot_Action_RefreshButtons(arg1);
end, end,
["UNIT_DISPLAYPOWER"] = function(this, arg1) ["UNIT_DISPLAYPOWER"] = function(this, arg1)
if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1) HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end end
@@ -201,8 +208,6 @@ local HealBot_EventHandlers = {
["SPELLCAST_FAILED"] = function(this) HealBot_OnEvent_SpellcastStop(this, "SPELLCAST_FAILED") end, ["SPELLCAST_FAILED"] = function(this) HealBot_OnEvent_SpellcastStop(this, "SPELLCAST_FAILED") end,
["PLAYER_REGEN_DISABLED"] = function(this) HealBot_OnEvent_PlayerRegenDisabled(this) end, ["PLAYER_REGEN_DISABLED"] = function(this) HealBot_OnEvent_PlayerRegenDisabled(this) end,
["PLAYER_REGEN_ENABLED"] = function(this) HealBot_OnEvent_PlayerRegenEnabled(this) end, ["PLAYER_REGEN_ENABLED"] = function(this) HealBot_OnEvent_PlayerRegenEnabled(this) end,
["BAG_UPDATE_COOLDOWN"] = function(this, arg1) HealBot_OnEvent_BagUpdateCooldown(this, arg1) end,
["BAG_UPDATE"] = function(this, arg1) HealBot_OnEvent_BagUpdate(this, arg1) end,
["PARTY_MEMBER_DISABLE"] = function(this, arg1) HealBot_OnEvent_PartyMemberDisable(this, arg1) end, ["PARTY_MEMBER_DISABLE"] = function(this, arg1) HealBot_OnEvent_PartyMemberDisable(this, arg1) end,
["PARTY_MEMBER_ENABLE"] = function(this, arg1) HealBot_OnEvent_PartyMemberEnable(this, arg1) end, ["PARTY_MEMBER_ENABLE"] = function(this, arg1) HealBot_OnEvent_PartyMemberEnable(this, arg1) end,
["CHAT_MSG_SYSTEM"] = function(this, arg1) HealBot_OnEvent_SystemMsg(this, arg1) end, ["CHAT_MSG_SYSTEM"] = function(this, arg1) HealBot_OnEvent_SystemMsg(this, arg1) end,
@@ -212,11 +217,10 @@ local HealBot_EventHandlers = {
HealBot_OnEvent_PlayerEquipmentChanged(this) HealBot_OnEvent_PlayerEquipmentChanged(this)
end, end,
["UNIT_INVENTORY_CHANGED"] = function(this, arg1) ["UNIT_INVENTORY_CHANGED"] = function(this, arg1)
if arg1 ~= "player" then return end
HealBot_Model:NotifyObservers("EQUIPMENT_CHANGED", arg1) HealBot_Model:NotifyObservers("EQUIPMENT_CHANGED", arg1)
HealBot_OnEvent_PlayerEquipmentChanged2(this, arg1) HealBot_OnEvent_PlayerEquipmentChanged2(this, arg1)
end, end,
["PET_BAR_SHOWGRID"] = function(this) HealBot_OnEvent_PartyMembersChanged(this) end,
["PET_BAR_HIDEGRID"] = function(this) HealBot_OnEvent_PartyMembersChanged(this) end,
["UNIT_PET"] = function(this, arg1) HealBot_OnEvent_PartyMembersChanged(this) end, ["UNIT_PET"] = function(this, arg1) HealBot_OnEvent_PartyMembersChanged(this) end,
["SPELLS_CHANGED"] = function(this, arg1) HealBot_OnEvent_SpellsChanged(this, arg1) end, ["SPELLS_CHANGED"] = function(this, arg1) HealBot_OnEvent_SpellsChanged(this, arg1) end,
["UPDATE_SHAPESHIFT_FORM"] = function(this) HealBot_UpdateShapeshiftForm() end, ["UPDATE_SHAPESHIFT_FORM"] = function(this) HealBot_UpdateShapeshiftForm() end,
@@ -288,8 +292,6 @@ function HealBot_OnEvent_VariablesLoaded(this)
this:RegisterEvent("PARTY_MEMBERS_CHANGED"); this:RegisterEvent("PARTY_MEMBERS_CHANGED");
this:RegisterEvent("PARTY_MEMBER_DISABLE"); this:RegisterEvent("PARTY_MEMBER_DISABLE");
this:RegisterEvent("PARTY_MEMBER_ENABLE"); this:RegisterEvent("PARTY_MEMBER_ENABLE");
this:RegisterEvent("PET_BAR_SHOWGRID");
this:RegisterEvent("PET_BAR_HIDEGRID");
this:RegisterEvent("UNIT_PET"); this:RegisterEvent("UNIT_PET");
this:RegisterEvent("UNIT_HEALTH"); this:RegisterEvent("UNIT_HEALTH");
this:RegisterEvent("UNIT_MANA"); this:RegisterEvent("UNIT_MANA");
@@ -301,8 +303,6 @@ function HealBot_OnEvent_VariablesLoaded(this)
this:RegisterEvent("SPELLCAST_STOP"); this:RegisterEvent("SPELLCAST_STOP");
this:RegisterEvent("SPELLCAST_INTERRUPTED"); this:RegisterEvent("SPELLCAST_INTERRUPTED");
this:RegisterEvent("SPELLCAST_FAILED"); this:RegisterEvent("SPELLCAST_FAILED");
this:RegisterEvent("BAG_UPDATE");
this:RegisterEvent("BAG_UPDATE_COOLDOWN");
this:RegisterEvent("UNIT_AURA"); this:RegisterEvent("UNIT_AURA");
this:RegisterEvent("UPDATE_INVENTORY_ALERTS"); this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
this:RegisterEvent("UNIT_INVENTORY_CHANGED"); this:RegisterEvent("UNIT_INVENTORY_CHANGED");
@@ -442,20 +442,6 @@ function HealBot_OnEvent_TalentsChanged(this, arg1)
HealBot_AddDebug("HB: TalentsChanged"); HealBot_AddDebug("HB: TalentsChanged");
end end
function HealBot_OnEvent_BagUpdate(this, bag)
if HealBot_EquipChangeTimer == 0 then
HealBot_RecalcSpells();
end
end
function HealBot_OnEvent_BagUpdateCooldown(this, bag)
if not bag then
bag = "undef"
elseif HealBot_EquipChangeTimer == 0 then
HealBot_RecalcSpells();
end
end
function HealBot_OnEvent_PlayerEnteringWorld(this) function HealBot_OnEvent_PlayerEnteringWorld(this)
HealBot_IsFighting = false; HealBot_IsFighting = false;
-- Re-apply the refresh hook late in case another addon overrode it during load -- Re-apply the refresh hook late in case another addon overrode it during load
+1 -1
View File
@@ -545,7 +545,7 @@ HealBot_Debuff_Types = {
HealBot_IsFighting = false; HealBot_IsFighting = false;
HealBot_DebuffPriority = {"none"}; HealBot_DebuffPriority = {"none"};
HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]="NO", [HEALBOT_MAGIC_en]="NO", [HEALBOT_POISON_en]="NO", [HEALBOT_CURSE_en]="NO"}; HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]=false, [HEALBOT_MAGIC_en]=false, [HEALBOT_POISON_en]=false, [HEALBOT_CURSE_en]=false};
HealBot_Heals = {}; HealBot_Heals = {};
+3 -3
View File
@@ -247,16 +247,16 @@ function HealBot_Options_Debuff_Reset()
local classEN=HealBot_UnitClass("player") local classEN=HealBot_UnitClass("player")
if classEN=="PRIEST" or classEN=="DRUID" or classEN=="PALADIN" or classEN=="SHAMAN" then if classEN=="PRIEST" or classEN=="DRUID" or classEN=="PALADIN" or classEN=="SHAMAN" then
local spell = HealBot_Config.CDCLeftText[UnitClass("player")]; local spell = HealBot_Config.CDCLeftText[UnitClass("player")];
HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]="NO", [HEALBOT_MAGIC_en]="NO", [HEALBOT_POISON_en]="NO", [HEALBOT_CURSE_en]="NO" } HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]=false, [HEALBOT_MAGIC_en]=false, [HEALBOT_POISON_en]=false, [HEALBOT_CURSE_en]=false }
if spell ~= "None" then if spell ~= "None" then
table.foreach(HealBot_Debuff_Types[spell], function (index,debuff) table.foreach(HealBot_Debuff_Types[spell], function (index,debuff)
HealBot_DebuffWatch[debuff]="YES"; HealBot_DebuffWatch[debuff]=true;
end) end)
end end
spell = HealBot_Config.CDCRightText[UnitClass("player")]; spell = HealBot_Config.CDCRightText[UnitClass("player")];
if spell ~= "None" then if spell ~= "None" then
table.foreach(HealBot_Debuff_Types[spell], function (index,debuff) table.foreach(HealBot_Debuff_Types[spell], function (index,debuff)
HealBot_DebuffWatch[debuff]="YES"; HealBot_DebuffWatch[debuff]=true;
end) end)
end end
end end
+4
View File
@@ -47,6 +47,10 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
* **Memory Optimization:** Fixed severe Lua garbage collection spikes during UI reloads by preventing full party layout rebuilds on `PLAYER_TARGET_CHANGED`, and cached dynamic string concatenations directly to unit frames to eliminate memory leakage on high frequency UI refreshes. * **Memory Optimization:** Fixed severe Lua garbage collection spikes during UI reloads by preventing full party layout rebuilds on `PLAYER_TARGET_CHANGED`, and cached dynamic string concatenations directly to unit frames to eliminate memory leakage on high frequency UI refreshes.
* **Mana Validation Fix:** Removed artificial spell mana gating, fixing an issue where low-mana spells disappeared from tooltips and couldn't be cast. WoW's native mana validation now correctly processes 0-cost buffs (e.g. Clearcasting, Inner Focus) while turning low-mana tooltip spells red. * **Mana Validation Fix:** Removed artificial spell mana gating, fixing an issue where low-mana spells disappeared from tooltips and couldn't be cast. WoW's native mana validation now correctly processes 0-cost buffs (e.g. Clearcasting, Inner Focus) while turning low-mana tooltip spells red.
* **Self-Buff Tracking:** Fixed a bug where "Self Only" buff tracking incorrectly excluded the player when represented by party or raid frames instead of the standard "player" unit ID. * **Self-Buff Tracking:** Fixed a bug where "Self Only" buff tracking incorrectly excluded the player when represented by party or raid frames instead of the standard "player" unit ID.
* **Settings Persistence Fix:** Changed `SavedVariables` to `SavedVariablesPerCharacter` in TOC so configurations correctly load unique per character instead of account-wide.
* **CPU Optimization:** Added early exit logic to resource tracking events (Mana, Rage, Energy) to stop background polling on party/raid members when "Show Mana Bars" is toggled off. Also removed excessive triggers (`BAG_UPDATE`, `PET_BAR_SHOWGRID`) and filtered `UNIT_INVENTORY_CHANGED` to only process the player, eliminating massive CPU spikes and unnecessary UI layout rebuilds during looting, item cooldowns, or when other players change gear.
* **OnUpdate GC Spike Fix:** Rewrote the modifier polling logic inside `HealBot_OnUpdate` to use boolean state tracking instead of dynamic string concatenation, eliminating a major source of garbage collection bloat while hovering over unit frames.
* **Aura Scanning Optimization:** Refactored Debuff tracking (`HealBot_DebuffWatch`) to use native boolean values (`true`/`false`) instead of string comparisons (`"YES"`/`"NO"`). This improves performance inside the continuous aura scanning loops.
**v1.5** **v1.5**
* **Macro, Item, and Script Bindings:** Support for binding named macros, inventory items, and inline scripts (e.g. `/target`) directly to mouse clicks in the Spells tab. All of these now natively support implicit `@mouseover` targeting on the unit frame you click, without losing your current target. * **Macro, Item, and Script Bindings:** Support for binding named macros, inventory items, and inline scripts (e.g. `/target`) directly to mouse clicks in the Spells tab. All of these now natively support implicit `@mouseover` targeting on the unit frame you click, without losing your current target.