WoW CPUThieves addon Dragonflight/Wrath of the Lich King Classic 2024
wow addon CPUThieves


Game Version: 6.0.3
Total Downloads: 2,780
Updated: Nov 3, 2014
Created: Oct 31, 2014
download CPUThievesDownload Earlier Versions

Earlier Versions

Name Size Uploaded Game Version Downloads
r11 release 9.96 KB Nov 3, 2014 6.0.3 2,062 download CPUThieves r11 releaseDownload
r10 release 9.73 KB Nov 3, 2014 6.0.3 94 download CPUThieves r10 releaseDownload
r9 release 9.35 KB Nov 2, 2014 6.0.3 80 download CPUThieves r9 releaseDownload
r8 release 8.15 KB Nov 2, 2014 6.0.3 99 download CPUThieves r8 releaseDownload
r7 release 7.52 KB Nov 2, 2014 6.0.3 60 download CPUThieves r7 releaseDownload
r5 release 4.87 KB Nov 1, 2014 6.0.3 80 download CPUThieves r5 releaseDownload
r4 release 4.83 KB Nov 1, 2014 6.0.3 71 download CPUThieves r4 releaseDownload
r3 beta 4.74 KB Nov 1, 2014 6.0.3 76 download CPUThieves r3 betaDownload
r2 beta 4.17 KB Oct 31, 2014 6.0.3 98 download CPUThieves r2 betaDownload
r6 alpha 7.36 KB Nov 2, 2014 6.0.3 60 download CPUThieves r6 alphaDownload


Share this:

This addon makes an attempt at spotting CPU thieves live and reporting about them. You probably don't want to use this if you don't have WoW Lua developer experience.

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


It needs CPU profiling to do its work, which is enabled via the command line: /cputhieves enable

! Remember to /cputhieves disable when you are done profiling!

It WILL try to report on excessive CPU usage during combat, but note that this is not a cheap operation, so it may actually trigger the 200ms execution limit set by Blizzard, leading to Lua errors, and probably more reports followed by more errors. If this happens to you, load fewer addons while doing these tests, or get a faster CPU 😀

How to parse the output

Note that the (123 = Lua) on the first line comes from Blizzard's GetScriptCPUUsage() API which seems a bit random in what it returns – probably it's timing related and I can't be arsed to figure it out right now. Sorry!

For AddOn CPU usage, you need to remember that it counts time spent in functions CREATED by a given addon, so often something like Ace3 will be showing high. Also, it will NOT count any time spent inside APIs – even those that use lots of time – so the time for an addon might show lower than it actually is.

For Frame CPU usage (items reported with an "F:" before the name), time spent inside APIs will be correctly counted. But note that frames with the same handler function will all show the same CPU time spent, which CPUThieves (half-heartedly) tries to hide some of. This becomes very visible if something gets blamed on the ChatFrames – there's 10 of them!

For Function CPU usage (items reported with "()"), it also includes the time of all subroutines called, so in e.g. a 150ms hickups you might see several functions taking almost 150ms each. This is expected.

Important Blizzard oddities

You should know:

GetFrameCPUTime() on its own only returns the total time used by its CURRENTLY set script functions, none of the past ones.

CPUThieves keeps track of all OnUpdate and OnEvent scripts that it has SEEN a frame use, and sums them all up. This should prevent the worst effects of addons switching their scripts live, but is not guaranteed to work 100% – we can still miss out on things between polling cycles!

C_Timer timers tend to not show up in either Frame or AddOn CPU (but sometimes they do, hrm..). This is why CPUThieves monitors timer functions explicitly.

More advanced

/cputhieves stats [N] will show the top N/7 addons & frames by total CPU time used:

CPUThieves: Tracking total 234 addons, 16247 frames
CPUThieves: Addons by total CPU:
CPUThieves:   5.8s !CPUThieves
CPUThieves:   1.3s Ace3
CPUThieves:   0.8s Overachiever
CPUThieves:   0.6s QuestCompletist
CPUThieves:   0.6s Pawn
CPUThieves:   0.3s WeakAuras
CPUThieves:   0.3s SavedInstances
CPUThieves: Frames by total CPU:
CPUThieves:   1.5s UnnamedFrame2C2EA960
CPUThieves:   1.3s F:AceEvent30Frame
CPUThieves:   1.1s F:AceAddon30Frame
CPUThieves:   1.1s F:PawnUIFrame
CPUThieves:   0.7s F:qcQuestCompletistUI
CPUThieves:   0.5s F:Atr_core
CPUThieves:   0.4s F:UIParent
CPUThieves: CPUThieves uses about 4.3ms per frame. Worst seen: 23.4ms

It is normal for !CPUThieves to use plenty of CPU time itself since it needs to keep looping through all addons and frames to stay up-to-date with their CPU usages (to know which addon used extra CPU when FPS hickups are detected!)

/cputhieves reset will reset these timers.

/cputhieves output lets you move the alerting to another ChatFrame (or anything with a :AddMessage function)

Identifying unnamed frames and functions

All unnamed frames that use high CPU are assigned a global name e.g. UnnamedFrame01234567 and reported as such. This allows you to prod it yourself with e.g. /dump
Unnamed functions (usually detected via C_Timer usage) are assigned a global name e.g. Function01234567 and reported as such.

Also try /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
    It will take a second or two to complete with all the variable scanning. Don't worry, your WoW didn't hang.


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 at startup (the "!" in "!CPUThieves" means we load before pretty much everything else)


CPUThieves logs all its output into its savedvariables file, in a rotating 1000-line buffer, timestamped:

CPUThievesDB = {
	["chatFrame"] = "ChatFrame1",
	["log"] = {
		"06:21:06 CPUThieves:   2.7s F:UIParent", -- [1]
		"06:21:06 CPUThieves:   1.4s F:table: 000000001B190C60", -- [2]
-- 8< --
		"07:13:10 CPUThieves:     56 49.7s !CPUThieves", -- [485]
		"05:24:34 CPUThieves:    110  0.7s F:ChatFrame7EditBox", -- [486]
--- 8< --
		"06:21:06 CPUThieves:   3.6s F:AceEvent30Frame", -- [999]
		"06:21:06 CPUThieves:   3.5s F:AceAddon30Frame", -- [1000]
		["n"] = 485,

The ["n"] entry shows where it wrote last.


Add a comment