It'll monitor for FPS hickups and spit out recent CPU usages like:
CPUThieves: Detected 182ms FPS hickup DURING COMBAT. (174ms = Lua)
CPUThieves: 170 0.2s WowLua
CPUThieves: 170 0.2s F:WowLuaButton_Config
CPUThieves: .. and 3 more frames with same handler function
CPUThieves: 170 0.2s F:WowLuaButton_Previous
CPUThieves: 170 0.2s F:WowLuaButton_Next
CPUThieves: 170 0.2s F:WowLuaButton_Redo
CPUThieves: .. and 5 more frames with same handler function
Yes, it requires profiling enabled, obviously. Which makes it suck in raid on a subpar CPU. I can't help you there, sorry :P
I will also point out that GetFrameCPUUsage() has MANY MANY quirks. If you see funny situations with frames spamming you with excessive CPU usage reports, but you can clearly see for yourself that nothing is going on ... sorry, I can't fix it.
So... unnamed, unparented frames. Very unhelpful to find out what addon it is.
Any useful ideas on how to identify them?
I optimistically tried issecurevariable(theFrame, 0) but it turns out that you can't even do this with nonstring table indices (argh blizzard). (It always returns true,nil - the same it does with nonexistant indices)
IF the frame table has other members, they can certainly be identified, but what if it doesn't have any? (All 3 high-CPU frames I see in my system right now only has the )
Then I thought about :GetScript("OnEvent"/"OnUpdate"/etc) .. but that only gets me a function reference which I can't do much with unless someone named the code chunk in question (fat chance).
- OnUpdate CPU usage now included in frame CPU usage (manual polling yay). Addon checks if this is necessary or not on start-up. (Future safe)
- If we ever report high CPU on an unnamed frame, it is now assigned a global name e.g. UnnamedFrame01234567 and reported as such. This allows you to prod it yourself with e.g. /dump
- New command "/cputhieves identify VARNAME" that does its best to find out just where the hell that variable came from.
- - It loops through ALL global vars&tables, up to 6 deep, trying to find someone pointing at it
- - For frames, it loops ALL Script handlers and does the same global scan
- - For any table, it loops all members and does issecurevariable() on them, trying to find mention of addons
If anyone else has any creative ideas on how to identify unnamed frames, I'm all ears!
We now track all OnEvent/OnUpdate that we have seen a frame use, and include their CPU usage in the stats. This doesn't necessarily mean all the ones that it ever used (we might have missed it between polls!), but it's a lot better than nothing.
Add in CPU polling of individual functions.
This is a VERY GOOD idea because:
1. C_Timer based timers tend to not show up in AddOn/Frame CPU usage (sometimes yes sometimes no - unsure why so far)
2. API calls that take time do not show up as AddOn time
By default, we monitor:
- C_Timer callouts (and where they were registered the first time)
- All GameTooltip APIs (you'd be surprised how much time they take!)
- All functions in the global namespace on startup (the "!" in "!CPUThieves" means we load before pretty much everything else)