View Single Post
11/25/14, 11:40 AM   #21
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
I tried with only backpack first (85/100 items), without marking anything with ItemSaver and all 4 icons red. Kept switching basic filters and AF subfilters for a few minutes. After a while it slowed down noticeably. Each click generated 2-6 calls to UpdateFilteredList in libFilters, causing up to 300k filter checks total (without early return optimization, which could hide the real problem, so I put it off for now).

As circonian found out, first problem is full inventory update after each register/unregister. Even when you know in advance you're going to register/unregister multiple filters, so you know the update is only needed after the last one, you have no way of telling libFilters to defer the update. This needs to be changed in libFilters. Either by a) suppress-updates parameter to register/unregister, or b) lock/unlock-for-updates functions, or c) require explicit update call. a) and b) would be backward-compatible, I like c) (it would allow changing some filter's settings/behavior without re-registering).


With a pair of greaves reserved for research, and the corresponding icon turned green, the delay with each tab switch is huge, even with "only" 50-100k filter checks, even on tabs other than apparel. I measured UpdateFilteredList and it took longer and longer, quickly went from ~20ms to >100ms per call as I was switching tabs (146/150 items in bank).


The slowdown is much bigger with Item Saver because AF filters are really simple and fast. Before I get to the real solution, you should try to optimize your FilterSavedItems* functions.
* call getSettingsIsFilterOn once per i, store the result in a local variable and use that in if/elseif conditions
* same with GetItemInstanceId, call once before the loop
* what's the purpose of SignItemId? Does the API sometimes return positive and sometimes negative value for the same item? Unless it does, get rid of it
* wrap debugMessage(..., true) calls in if (settings.deepDebug) then debugMessage(...) end; the way you have it now, you compose the whole message, which is quite expensive, only to throw it away if deepDebug is disabled.


Now to the core problem. libFilters in SetInventoryFilter chains additionalFilter. There's a comment saying additionalFilter vanishes when layout changes, which happens when you switch from Bank to Guild Store for example, but apparently it persists and gets chained after the next. This needs to be fixed, because now it creates an ever-expanding chain of functions doing the same thing. You can easily get to 50 filter calls per slot, and early return optimization only helps with items that don't pass some filter - those that pass all filters go through the whole chain.


Totally off-topic, bag slot indices start from 0:
Lua Code:
  1. -- replace
  2. for slotIndex = 1, GetBagSize(bagId) do
  3. -- with
  4. for slotIndex = 0, GetBagSize(bagId) - 1 do
  Reply With Quote