Thread Tools Display Modes
04-29-18, 05:54 AM   #1
Edik
A Murloc Raider
 
Edik's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 5
Wraper functions for 8.0.1 spell/aura changes

I have set of functions to wrap changes without no need to modify old code for transcending period in addon development. It allows still use code in 7.3 and 8.x. Just replace P. with your add-on name and then inlude at start of your code:

Lua Code:
  1. local GetSpellInfo = P.GetSpellInfo; assert(GetSpellInfo ~= nil,'GetSpellInfo')

If you want to use GetSpellInfo without need to worry about client version. Here are wrappers

Lua Code:
  1. -- LINT frinedly declaration
  2. local GetBuildInfo = _G.GetBuildInfo; assert(GetBuildInfo ~= nil,'GetBuildInfo')
  3. -- transience 7.x na 8.x
  4. local _, _, _, tocVersion = GetBuildInfo() -- resolve version
  5. -- wrappers
  6. function P.UnitChannelInfo(unit) -- 7.x to 8.x transience 2nd return value removed
  7.   if tocVersion < 80000 then return _G.UnitChannelInfo(unit) end
  8.   local retTable = {_G.UnitChannelInfo(unit)}
  9.   if retTable[1] then table.insert(retTable,2,'') end
  10.   return unpack(retTable)
  11. end
  12. function P.UnitCastingInfo(...) -- 7.x to 8.x transience 2nd return value removed
  13.   if tocVersion < 80000 then return _G.UnitCastingInfo(...) end
  14.   local retTable = {_G.UnitCastingInfo(...)}
  15.   if retTable[1] then table.insert(retTable,2,'') end
  16.   return unpack(retTable)
  17. end
  18. function P.GetSpellInfo(...) -- 7.x to 8.x transience 2nd return value replaced with nil
  19.   if tocVersion < 80000 then return _G.GetSpellInfo(...) end
  20.   local retTable = {_G.GetSpellInfo(...)}
  21.   if retTable[1] then retTable[2] = '' end
  22.   return unpack(retTable)
  23. end
  24. function P.GetMacroSpell(...) -- 7.x to 8.x transience 1st and 2nd return value removed
  25.   if (tocVersion < 80000) then return _G.GetMacroSpell(...) end
  26.   local retTable = {_G.GetMacroSpell(...)}
  27.   if retTable[1] then
  28.     local name = _G.GetSpellInfo(retTable[1])
  29.     if name then
  30.       table.insert(retTable,1,'')
  31.       table.insert(retTable,1,name)
  32.     end
  33.   end
  34.   return unpack(retTable)
  35. end
  36. function P.GetPetActionInfo(...) -- 7.x to 8.x transience 2nd return value removed
  37.   if (tocVersion < 80000) then return _G.GetPetActionInfo(...) end
  38.   local retTable = {_G.GetPetActionInfo(...)}
  39.   if retTable[1] then table.insert(retTable,2,'') end
  40.   return unpack(retTable)
  41. end
  42. function P.GetPossessInfo(...) -- 7.x to 8.x transience 2nd return value changed from spell name to spell ID.
  43.   if (tocVersion < 80000) then return _G.GetPossessInfo(...) end
  44.   local retTable = {_G.GetPossessInfo(...)}
  45.   if retTable[2] then
  46.     local name = _G.GetSpellInfo(retTable[2])
  47.     retTable[2] = name
  48.   end
  49.   return unpack(retTable)
  50. end
  51. function P.GetItemSpell(...) -- 7.x to 8.x transience 2nd return value removed
  52.   if (tocVersion < 80000) then return _G.GetItemSpell(...) end
  53.   local retTable = {_G.GetItemSpell(...)}
  54.   if retTable[1] then table.insert(retTable,2,'') end
  55.   return unpack(retTable)
  56. end
  57. function P.GetSpellLink(...) -- 7.x to 8.x transience 2nd return value removed
  58.   if (tocVersion < 80000) then return _G.GetSpellLink(...) end
  59.   local retTable = {_G.GetSpellLink(...)}
  60.   if retTable[1] then table.insert(retTable,2,_G.GetSpellTradeSkillLink(...)) end
  61.   return unpack(retTable)
  62. end
  63. local UnitAuraCache = {} -- cached values are updated ten times per second and stored by unit+filter
  64. function P.UnitAura(unit, ...) -- 7.x to 8.x transience 2nd return value removed and only spellID argument is supported
  65.   if tocVersion < 80000 then return _G.UnitAura(unit, ...) end
  66.   local retTable
  67.   local index = select(1,...)
  68.   if type(index) == 'number' then -- now only spellID is accepted
  69.     retTable = {_G.UnitAura(unit, ...)}
  70.     if retTable[1] then table.insert(retTable,2,'') end
  71.   elseif type(index) == 'string' then -- lokup by spellName must be done on own by fetching all auras and then looking up by name
  72.     local index, _, filter = select(1,...)
  73.     local key = string.lower(filter or 'default')
  74.     index = string.lower(index) -- lookup by spell name
  75.     unit = string.lower(unit)
  76.     local cache = UnitAuraCache[unit] -- fetch unit aura cache
  77.     if cache and cache[key] and cache[key]['stamp'] == ("%.1f"):format(GetTime()) then -- cached values updated 10 times per second
  78.       if cache[key][index] then retTable = cache[key][index] else retTable = {} end
  79.     else -- fetch new cached values
  80.       if not UnitAuraCache[unit] then UnitAuraCache[unit] = {} end
  81.       if not UnitAuraCache[unit][key] then UnitAuraCache[unit][key] = {} else table.wipe(UnitAuraCache[unit][key]) end
  82.       cache = UnitAuraCache[unit][key]
  83.       local n = 1
  84.       local name
  85.       repeat
  86.         retTable = {_G.UnitAura(unit, n, filter)}
  87.         name = retTable[1]
  88.         if name then
  89.           table.insert(retTable,2,'')
  90.           cache[string.lower(name)] = table.copy(retTable)
  91.         end
  92.         n = n + 1
  93.       until not name;
  94.       cache['stamp'] = ("%.1f"):format(GetTime())
  95.       if cache[index] then
  96.         retTable = cache[index]
  97.       else
  98.         retTable = {nil}
  99.       end
  100.     end
  101.   end
  102.   return unpack(retTable)
  103. end
  104. local UnitBuffCache = {} -- cached values are updated ten times per second and stored by unit+filter
  105. function P.UnitBuff(unit, ...) -- 7.x to 8.x transience 2nd return value removed and only spellID argument is supported
  106.   if tocVersion < 80000 then return _G.UnitBuff(unit, ...) end
  107.   local retTable
  108.   local index = select(1,...)
  109.   if type(index) == 'number' then -- now only spellID is accepted
  110.     retTable = {_G.UnitBuff(unit, ...)}
  111.     if retTable[1] then table.insert(retTable,2,'') end
  112.   elseif type(index) == 'string' then -- lokup by spellName must be done on own by fetching all auras and then looking up by name
  113.     local index, _, filter = select(1,...)
  114.     local key = string.lower(filter or 'default')
  115.     index = string.lower(index) -- lookup by spell name
  116.     unit = string.lower(unit)
  117.     local cache = UnitBuffCache[unit] -- fetch unit aura cache
  118.     if cache and cache[key] and cache[key]['stamp'] == ("%.1f"):format(GetTime()) then -- cached values updated 10 times per second
  119.       if cache[key][index] then retTable = cache[key][index] else retTable = {} end
  120.     else -- fetch new cached values
  121.       if not UnitBuffCache[unit] then UnitBuffCache[unit] = {} end
  122.       if not UnitBuffCache[unit][key] then UnitBuffCache[unit][key] = {} else table.wipe(UnitBuffCache[unit][key]) end
  123.       cache = UnitBuffCache[unit][key]
  124.       local n = 1
  125.       local name
  126.       repeat
  127.         retTable = {_G.UnitBuff(unit, n, filter)}
  128.         name = retTable[1]
  129.         if name then
  130.           table.insert(retTable,2,'')
  131.           cache[string.lower(name)] = table.copy(retTable)
  132.         end
  133.         n = n + 1
  134.       until not name;
  135.       cache['stamp'] = ("%.1f"):format(GetTime())
  136.       if cache[index] then
  137.         retTable = cache[index]
  138.       else
  139.         retTable = {nil}
  140.       end
  141.     end
  142.   end
  143.   return unpack(retTable)
  144. end
  145. local UnitDebuffCache = {} -- cached values are updated ten times per second and stored by unit+filter
  146. function P.UnitDebuff(unit, ...) -- 7.x to 8.x transience 2nd return value removed and only spellID argument is supported
  147.   if tocVersion < 80000 then return _G.UnitDebuff(unit, ...) end
  148.   local retTable
  149.   local index = select(1,...)
  150.   if type(index) == 'number' then -- now only spellID is accepted
  151.     retTable = {_G.UnitDebuff(unit, ...)}
  152.     if retTable[1] then table.insert(retTable,2,'') end
  153.   elseif type(index) == 'string' then -- lokup by spellName must be done on own by fetching all auras and then looking up by name
  154.     local index, _, filter = select(1,...)
  155.     local key = string.lower(filter or 'default')
  156.     index = string.lower(index) -- lookup by spell name
  157.     unit = string.lower(unit)
  158.     local cache = UnitDebuffCache[unit] -- fetch unit aura cache
  159.     if cache and cache[key] and cache[key]['stamp'] == ("%.1f"):format(GetTime()) then -- cached values updated 10 times per second
  160.       if cache[key][index] then retTable = cache[key][index] else retTable = {} end
  161.     else -- fetch new cached values
  162.       if not UnitDebuffCache[unit] then UnitDebuffCache[unit] = {} end
  163.       if not UnitDebuffCache[unit][key] then UnitDebuffCache[unit][key] = {} else table.wipe(UnitDebuffCache[unit][key]) end
  164.       cache = UnitDebuffCache[unit][key]
  165.       local n = 1
  166.       local name
  167.       repeat
  168.         retTable = {_G.UnitDebuff(unit, n, filter)}
  169.         name = retTable[1]
  170.         if name then
  171.           table.insert(retTable,2,'')
  172.           cache[string.lower(name)] = table.copy(retTable)
  173.         end
  174.         n = n + 1
  175.       until not name;
  176.       cache['stamp'] = ("%.1f"):format(GetTime())
  177.       if cache[index] then
  178.         retTable = cache[index]
  179.       else
  180.         retTable = {nil}
  181.       end
  182.     end
  183.   end
  184.   return unpack(retTable)
  185. end
  186. function P.GetPlayerMapPosition(...) -- 7.x to 8.x transinece function removed, this just simulate old function buth with different scale
  187.   if tocVersion < 80000 then return _G.GetPlayerMapPosition(...) end
  188.   local x, y = _G.UnitPosition(...)
  189.   if type(x) == 'number' and type(y) == 'number' then
  190.     x = x / 1000.0
  191.     y = y / 1000.0
  192.   end
  193.   return x, y
  194. end

Last edited by Edik : 04-30-18 at 11:58 PM.
  Reply With Quote
04-29-18, 04:08 PM   #2
boomboo
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Nov 2009
Posts: 4
From the limited tests I've done with cache tables (for UnitAura) it wasn't worth it, ie. the overhead of creating and copying tables was worse than just looping every time. (both from CPU and garbage being created perspectives)

Though my tests were done on 7.3 since I don't have access to beta yet.
  Reply With Quote
04-30-18, 05:21 AM   #3
Edik
A Murloc Raider
 
Edik's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 5
In 7.3 you won't need any caching. In 8.x is quering Aura by name completely removed. So if you have mutiple checks in single line I guess caching is worth to try. If you do by aura index from 1 to 40 old fashioned way you won't need to cache. Just imagine if you have this in your old code.

Lua Code:
  1. function WWM:isEating() -- am I bussy by feeding self?
  2.   return UnitAura(ID_PLAYER, BUFF_FOOD) or UnitAura(ID_PLAYER, BUFF_DRINK) or UnitAura(ID_PLAYER, BUFF_REFRESHMENT) or UnitAura(ID_PLAYER, BUFF_DRINK_AND_FOOD)
  3. end

I had my wrappers a small glitch I did fix it original post.

Last edited by Edik : 04-30-18 at 05:29 AM.
  Reply With Quote
04-30-18, 06:55 AM   #4
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
Your aura caching is utterly inefficient and in its current form actually useless. What is the point in hitting a cache which invalidates itself every 1/10 of a second?
  Reply With Quote
04-30-18, 08:42 AM   #5
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
@Rainrider
Just for info. This comes off pretty rude.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)
  Reply With Quote
04-30-18, 10:17 AM   #6
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
Originally Posted by zork View Post
@Rainrider
Just for info. This comes off pretty rude.
I'm sorry but I don't understand how it comes "pretty rude". Also I did respond to Edik and I think s/he is the one to complain if s/he felt offended.
  Reply With Quote
04-30-18, 12:28 PM   #7
boomboo
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Nov 2009
Posts: 4
Originally Posted by Edik View Post
In 7.3 you won't need any caching. In 8.x is quering Aura by name completely removed. So if you have mutiple checks in single line I guess caching is worth to try. If you do by aura index from 1 to 40 old fashioned way you won't need to cache. Just imagine if you have this in your old code.
I know, I was talking from the 8.x perspective, and the comparrisons I ran were with single spell querying. As I mentioned though the overhead of all the data being copied and cleared wasn't worth it. You could run the tests yorself but I doubt you'll get different results.

Also UnitAura doesn't support querying by spellid in either 7.3 or 8.x, the second argument if numeric is just an index.

Last edited by boomboo : 04-30-18 at 12:35 PM.
  Reply With Quote
04-30-18, 03:34 PM   #8
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
I used this for testing:
lua Code:
  1. local addon = ...
  2.  
  3. local UnitAuraCache = {} -- cached values are updated ten times per second and stored by unit+filter
  4. local function UnitAura(unit, ...) -- 7.x to 8.x transience 2nd return value removed and only spellID argument is supported
  5.     local retTable
  6.     local index = select(1,...)
  7.     if type(index) == 'number' then -- now only spellID is accepted
  8.         retTable = {_G.UnitAura(unit, ...)}
  9.         if retTable[1] then table.insert(retTable,2,'') end
  10.     elseif type(index) == 'string' then -- lokup by spellName must be done on own by fetching all auras and then looking up by name
  11.         local index, filter = select(1,...)
  12.         local key = string.lower(filter or 'default')
  13.         index = string.lower(index) -- lookup by spell name
  14.         unit = string.lower(unit)
  15.         local cache = UnitAuraCache[unit] -- fetch unit aura cache
  16.         if cache and cache[key] and cache[key][index] and cache[key]['stamp'] == ("%.1f"):format(GetTime()) then -- cached values updated 10 times per second
  17.             retTable = cache[key][index]
  18.         else
  19.             if not UnitAuraCache[unit] then UnitAuraCache[unit] = {} end
  20.             if not UnitAuraCache[unit][key] then UnitAuraCache[unit][key] = {} else table.wipe(UnitAuraCache[unit][key]) end
  21.             cache = UnitAuraCache[unit][key]
  22.             local n = 1
  23.             local name
  24.             repeat
  25.                 retTable = {_G.UnitAura(unit, n, filter)}
  26.                 name = retTable[1]
  27.                 if name then
  28.                     table.insert(retTable,2,'')
  29.                     cache[string.lower(name)] = retTable -- there is no table.copy
  30.                 end
  31.                 n = n + 1
  32.             until not name;
  33.             cache['stamp'] = ("%.1f"):format(GetTime())
  34.             if cache[index] then
  35.                 retTable = cache[index]
  36.             else
  37.                 retTable = {nil}
  38.             end
  39.         end
  40.     end
  41.     return unpack(retTable)
  42. end
  43.  
  44. local function GetAura(unit, ...)
  45.     local index = ...
  46.     if type(index) == 'number' then
  47.         local name, texture, count, debuffType, duration, expirationTime, caster, isStealable,
  48.             nameplateShowPersonal, spellId, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,
  49.             timeMod, effect1, effect2, effect3 = _G.UnitAura(unit, ...)
  50.         return name, '', texture, count, debuffType, duration, expirationTime, caster, isStealable,
  51.             nameplateShowPersonal, spellId, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,
  52.             timeMod, effect1, effect2, effect3
  53.     elseif type(index) == 'string' then
  54.         local auraName, filter = ...
  55.         auraName = string.lower(auraName)
  56.         for i = 1, 100 do
  57.             local name, texture, count, debuffType, duration, expirationTime, caster, isStealable,
  58.                 nameplateShowPersonal, spellId, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,
  59.                 timeMod, effect1, effect2, effect3 = _G.UnitAura(unit, i, filter)
  60.             if not name then return end
  61.             if string.lower(name) == auraName then
  62.                 return name, '', texture, count, debuffType, duration, expirationTime, caster, isStealable,
  63.                     nameplateShowPersonal, spellId, canApply, isBossDebuff, casterIsPlayer, nameplateShowAll,
  64.                     timeMod, effect1, effect2, effect3
  65.             end
  66.         end
  67.     end
  68. end
  69.  
  70. local function TestCached()
  71.     local start = debugprofilestop()
  72.  
  73.     for i = 1, 1e6 do
  74.         UnitAura('target', 'nothing')
  75.     end
  76.  
  77.     print('Execution time (cached):', debugprofilestop() - start)
  78. end
  79.  
  80. local function TestNotCached()
  81.     local start = debugprofilestop()
  82.  
  83.     for i = 1, 1e6 do
  84.         GetAura('target', 'nothing')
  85.     end
  86.  
  87.     print('Execution time (not cached):', debugprofilestop() - start)
  88. end
  89.  
  90. _G['SLASH_' .. addon .. '1'] = '/testaura'
  91. _G.SlashCmdList[addon] = function(msg)
  92.     msg = strlower(msg)
  93.     if msg == 'cached' then
  94.         TestCached()
  95.     else
  96.         TestNotCached()
  97.     end
  98. end

The changes I made to Edik's code were:
1. removed the toc check (tested on beta only)
2. local index, _, filter = select(1,...) - > local index, filter = select(1,...)
3. cache[string.lower(name)] = table.copy(retTable) -> cache[string.lower(name)] = retTable

On average the cached version is 4 times slower than with no caching.

The test is not fair at all as it does not compare only the caching! The aim here is just to provide a rough estimation.

Beware that GetTime() is cached by the client. This has side effects on Edik's implementation as well.

The GetAura function can be optimized further.

Please do not take the results as a contra cache statement. Caching may prove useful, but this depends a lot on the use case and the implementation.
  Reply With Quote
04-30-18, 04:05 PM   #9
boomboo
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Nov 2009
Posts: 4
It's not especially surprising since UnitAura is implemented in C (I presume), and might have it's own caching or optimizations. Adding stuff on top of it in lua doesn't help.

The best way to work around it is to probably reverse the loops for 8.x ie. instead of doing:
Code:
for list_of_spells_I_care_about {
  for 1, N {
    name, ... = UnitAura(, i, )
    if(name == list_of_spells_I_care_about[i]) do_whatever()
  }
}
do:
Code:
local list_of_spells_I_care_about_lookup_table
for 1, N {
  name, ... = UnitAura(, i, )
  if(list_of_spells_I_care_about_lookup_table[name]) do_whatever()
}
This way you're kind of cheating, since list_of_spells_I_care_about_lookup_table is a static list with a lookup cost O(1). This might not always be possible, depending on the addon / implementation.

Last edited by boomboo : 04-30-18 at 04:12 PM.
  Reply With Quote
04-30-18, 07:43 PM   #10
VincentSDSH
Non-Canadian Luzer!
 
VincentSDSH's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2006
Posts: 350
Originally Posted by boomboo View Post
Code:
local list_of_spells_I_care_about_lookup_table
for 1, N {
  name, ... = UnitAura(, i, )
  if(list_of_spells_I_care_about_lookup_table[name]) do_whatever()
}
This is what I've used and I'm quite happy with the result, for multi-checks. It's a bit much overhead for single checks, though. I haven't decided if I prefer an overloaded version or just a different call.
__________________
AddonsExecutive Assistant User Configurable To-Do ListLegible Mail Choose the Font for Your Mail
  Reply With Quote
04-30-18, 11:29 PM   #11
Edik
A Murloc Raider
 
Edik's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 5
I must agree with most notes here. I found falw in my code. In fact it didn't cahe at all if query didn't hit exactly same aura. I fix it by:

Lua Code:
  1. if cache and cache[key] and cache[key]['stamp'] == ("%.1f"):format(GetTime()) then -- cached values updated 10 times per second
  2.       if cache[key][index] then retTable = cache[key][index] else retTable = {} end
  3.     else -- fetch new cached values

now it is really effective and overhead is small if multiple aura checks by name are done in one cycle (in split .1s). Keep in mind these wrappers are just for time period when code need to be 7.x compatible and you want to do just small or none changes for testing in 8.x. These functions aren't permanent for 8.x. I'm pretty sure that someone come with new UnitAUra, UnitBuff and UnitDebuff for quering aura by Name. BTW someone told about UnitAura doesn't support query by Name in 7.x I must disagree it does support. Form is UnitAura(unit,name[,[nameSubtext][,filter]]).

Last edited by Edik : 04-30-18 at 11:57 PM.
  Reply With Quote
04-30-18, 11:39 PM   #12
Edik
A Murloc Raider
 
Edik's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 5
Originally Posted by Rainrider View Post
Beware that GetTime() is cached by the client. This has side effects on Edik's implementation as well.

Please do not take the results as a contra cache statement. Caching may prove useful, but this depends a lot on the use case and the implementation.
I agree. GetTime() changing every frame update. When you have low FPS it could change only few times per second. But auras change few times per second as well if you care just about aura existence not about startTime, endTime is fine. That was target for these wrappers, just make code works at least in 8.x and do some backward compatibility.

Last edited by Edik : 04-30-18 at 11:59 PM.
  Reply With Quote
05-01-18, 07:17 AM   #13
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
Originally Posted by boomboo View Post
It's not especially surprising since UnitAura is implemented in C (I presume), and might have it's own caching or optimizations. Adding stuff on top of it in lua doesn't help.
Test again, but instead 'nothing' use the name of an aura you expect to find (like cast Rejuvenation on yourself and run the test with it). The cache is twice as fast (this is the best case however, since because of the use of GetTime() and the test freezing the client, the cache is hit every time except for the initial call)

Originally Posted by Edik View Post
I agree. GetTime() changing every frame update. When you have low FPS it could change only few times per second. But auras change few times per second as well if you care just about aura existence not about startTime, endTime is fine. That was target for these wrappers, just make code works at least in 8.x and do some backward compatibility.
Auras do not necessarily change that often. If GetTime() works as you intended it to run, you will have 10 times per second the worst case, which is 4 times slower than the direct loop over all auras. Also you don't invalidate the cache if the unit changes (I target another mob), so it might be possible to even get wrong results from hitting the cache (you might argue that I'll call UnitAura again soon enough to not even notice this, but it is still possible).

From my perspective a wrapper should be just that and not a cache on top of it.

The interesting part is the gap in performance between best and worst case and it makes it clear how inefficient your UnitAura calls are. You pack the results of UnitAura in a table and unpack it later for return. You also have all the table look-ups in between. What is the benefit from that? Also

lua Code:
  1. local index, filter = ...

is the same as
lua Code:
  1. local index, filter = select(1, ...)

but without the added function call.
  Reply With Quote
05-01-18, 05:51 PM   #14
boomboo
A Murloc Raider
AddOn Author - Click to view addons
Join Date: Nov 2009
Posts: 4
Originally Posted by Rainrider View Post
Test again, but instead 'nothing' use the name of an aura you expect to find (like cast Rejuvenation on yourself and run the test with it). The cache is twice as fast (this is the best case however, since because of the use of GetTime() and the test freezing the client, the cache is hit every time except for the initial call)
I never tested with `nothing`, my tests were done vs. a real training dummy over X minutes. There might be edge cases where using cache would be better (ie. for some reason you want to know about one specific debuff on a raid boss that wasn't applied by you).

In most other cases if you filter correctly (eg. use HARMFUL|PLAYER) the number of auras should be small enough to iterate over so that the overhead of creating / destroying the cache is worse than looping.
  Reply With Quote
05-02-18, 04:16 AM   #15
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
If you have a case where you query information about multiple auras upon every UNIT_AURA then a cache is useful. Basically you refresh your cache once on UNIT_AURA and all your queries always hit the cache. If your cache structure is shallow enough, the table look-ups will be faster then calling UnitAura. One problem with Edik's implementation is that auras are re-iterated on cache misses and the new iteration is also a miss. If you can't trust the cache, then there is no point in it.
  Reply With Quote

WoWInterface » PTR » PTR General Discussion » Wraper functions for 8.0.1 spell/aura changes

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off