Hey guys I’ve written my own addon and it’s…terrible. Well, it’s functional, but it is using way more CPU than it should. I was hoping to find some kind of debugging / profiling tools or commands or something I could use to track down and find my worst offenders – I don’t know which of my functions is draining so much performance. Any suggestions?
For profiling during development I use debugprofilestop() a lot to get a rough measure of the time it takes something to run.
local t = debugprofilestop()
-- do something computationally expensive maybe
print(debugprofilestop()-t)
Sometimes it’s useful to run it many times (keeping mind that cache behaviors may get involve or things not changing taking less computation effort) in a tight loop to get more noticable differences when optimizing:
local t = debugprofilestop()
for i=1,10000 do
-- do something
end
print(debugprofilestop()-t)
However, what you should be watching for also is how often your code runs.
Some developers might register for ZONE_CHANGED (or one of those events), confirm it works, and then not realize this event can potentially fire hundreds of times when crossing the middle of a zone. (Or it did during MoP when I was horrified to realize just how freakishly often this event fired.)
It’s a good idea to put a print(event) in your event handler just to get an idea of how often something runs. It’s quite common for events to come in spasms (thinking BAG_UPDATE when you equipset or move stuff around bags–we have BAG_UPDATE_DELAYED nowadays so it’s not as common a culprit). Chances are your addon doesn’t need to respond to every one of those events. My preference is to set up a throttle to wait X time after an event has stopped firing and act on it then.
This is a simple example of throttling. You can use C_Timer stuff to do it also.
local f = CreateFrame("Frame")
f:Hide()
f.timer = 0
f:SetScript("OnUpdate",function(self,elapsed)
self.timer = self.timer + elapsed
if self.timer > 0.5 then
self:Hide() -- stop OnUpdate
print("Doing stuff")
-- do stuff
end
end)
f:SetScript("OnEvent",function(self,event,...)
print(event,...)
self.timer = 0
self:Show() -- start OnUpdate
end)
f:RegisterEvent("BAG_UPDATE")
Speaking of OnUpdate, unless you have very very good reason for your code to run every frame (such as an animation), you generally want to use a timer even if not throttling stuff.
local f = CreateFrame("Frame")
f.timer = 0
f:SetScript("OnUpdate",function(self,elapsed)
self.timer = self.timer + elapsed
if self.timer > 0.2 then
self.timer = 0
print("Doing stuff")
end
end)
120/144 fps is not uncommon nowadays and even at 60 fps having an OnUpdate call every frame can mean your code is running 60 times a second. Not a huge deal by itself if the code is light, but if many addons are doing it, it can add up.
This is SO helpful, thank you! This is exactly what I was looking for. Time to get to work ![]()