Navigation menu
Personal tools
Not logged in
Talk
Contributions
Create account
Log in
Namespaces
WoW
Talk
English
Views
Read
Edit
History
More
Search
Navigation
Home
Random page
Help using wiki
Editions
for WoW
for WildStar
for Solar2D
Documentation
for WoW
for WildStar
Reference
WoW
⦁ FrameXML
⦁ AddOns
⦁ API
⦁ WoW Lua
WildStar
⦁ AddOns
⦁ API
⦁ WildStar Lua
Engine
Tools
What links here
Related changes
Special pages
Page information
Site
Recent Changes
Editing
WoW:HOWTO: Use Tables Without Generating Extra Garbage
Jump to navigation
Jump to search
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
{{wowlua}} Creating number and strings values is pretty efficient in Lua, Numbers do not have any additional data structure associated with them and are freed immediately when no longer used. Strings are hashed and stacked together with same strings, so creating 10000 copies of "Hello, world!" or creating and freeing it repeatedly will not produce garbage. Tables, however, always take memory when created that always becomes garbage when table is no longer used. If you do not want to create unnecessary garbage either avoid using tables unless it is really necessary or, in case several of your throw-away tables use same set of fields, or each new calculation uses superset of field of previous table, use only one table instead of creating new table for every calculation. For example, if you need to sort 20 values, display result and then sort another 30 and display them too, most people would write: local temporaryTable temporaryTable={} for idx=1, 20 do temporaryTable[idx]=GetSomeDataByIndex(idx) end DisplayResult(table.sort(temporaryTable)) temporaryTable={} -- inefficient for idx=1, 30 do temporaryTable[idx]=GetSomeOtherDataByIndex(idx) end DisplayResults(table.sort(temporaryTable)) This example would create one table, trash it after calculation and create another throw-away table again. Removing extra table constructor in line marked with "-- inefficient" will save you memory. Such optimization would be especially effective inside long loops or frequently called function. Old: local function OftenCalledSortingFunction() local temporaryTable={} for idx=1, 20 do temporaryTable[idx]=GetSomeDataByIndex(idx) end return table.sort(temporaryTable) end Placing call to this in frequently called event or even worse in "OnUpdate" handler is a sure way to fill your memory with garbage fast. New: local workingTableForOftenCalledSortingFunction={} -- we can create it once and reuse it because we always sort exactly 20 values local function OftenCalledSortingFunction() for idx=1, 20 do workingTableForOftenCalledSortingFunction[idx]=GetSomeDataByIndex(idx) end return table.sort(workingTableForOftenCalledSortingFunction) end You can futher maximize savings if some other functions too use table with same size/set of field by sharing this working table between them. Here's example straight from many addons that create UI dropdowns: local function MyAddon_InitMenu() local info info = {} info.text = "Settings Button1" info.value = "Some value" info.checked = PlayerSettings["Setting1"] UIDropDownMenu_AddButton(info); info = {}; info.text = "Settings Button2" info.value = "Some other value" info.checked = PlayerSettings["Setting2"] UIDropDownMenu_AddButton(info); -- end of settings buttons info = {}; info.text = "Action Button1" info.value = "Value to act on" info.func = function() DoSomething() end; UIDropDownMenu_AddButton(info); info = {}; info.text = "Action Button2" info.value = "Another value to act on" info.func = function() DoSomethingElse() end; UIDropDownMenu_AddButton(info); end If you ever written something like that, then your addon contributes 4 tables (in this example) to garbage every time this menu is displayed. And if you've used loops to dynamically generate long menus (listing all characters' profiles, for example) then you've lost even more. For efficient use of memory you can define <tt>info</tt> once, removing all <tt>info = {}</tt> lines and adding <tt>info.checked = nil</tt> string after end of settings buttons, to ensure that checked/unchecked state of last settings button doesn't appears on action buttons. This will reduce your losses to one trashed table per call. And, just like in previous example, you can use one permanent working table and eliminate garbage generation completely: -- UIDropDownMenu_AddButton only needs table to conveniently pass arguments by name -- All values are copied to their correct places inside UIDropDownMenu_AddButton -- and it doesn't need table we passed any longer after that. This allows us to -- reuse same table for passing parameters, since we know that reference to this -- table won't be saved anywhere as long as we use same fields and thus overwrite -- previous values automatically without need to clear working table in some way. local workingTableForInitMenu={} local function MyAddon_InitMenu() workingTableForInitMenu.func=nil -- erase value that could be there from last call workingTableForInitMenu.text = "Settings Button1" workingTableForInitMenu.value = "Some value" workingTableForInitMenu.checked = PlayerSettings["Setting1"] UIDropDownMenu_AddButton(workingTableForInitMenu) workingTableForInitMenu.text = "Settings Button2" workingTableForInitMenu.value = "Some other value" workingTableForInitMenu.checked = PlayerSettings["Setting2"] UIDropDownMenu_AddButton(workingTableForInitMenu) -- end of settings buttons workingTableForInitMenu.checked=nil -- erase value that could be there from last settings button workingTableForInitMenu.text = "Action Button1" workingTableForInitMenu.value = "Value to act on" workingTableForInitMenu.func = function() DoSomething() end; UIDropDownMenu_AddButton(workingTableForInitMenu) workingTableForInitMenu.text = "Action Button2" workingTableForInitMenu.value = "Another value to act on" workingTableForInitMenu.func = function() DoSomethingElse() end; UIDropDownMenu_AddButton(workingTableForInitMenu) end Finally, let me stress once again: this works best when you have table of same size or with same set of fields. As you see from the last example, buttons differ by two fields and function now has to take care of that. Forgetting this while using this approach can produce some very funny and hard to track bugs. And clearing table from previous values can degrade performance if there are many fields to clear on each run. Another thing to be aware of is that unlike <tt>UIDropDownMenu_AddButton</tt>, some function may store table reference and check values from it at some point in future, hoping that nobody else uses this table. When such function do that in future only to get something else that was initially passed, they tend to mess things up in quite spectacular ways. Check the target function to make sure that it doesn't store passed table. [[Category:HOWTOs|Use Tables Without Generating Extra Garbage]]
Summary:
Please note that all contributions to AddOn Studio are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see
AddOn Studio Wiki:Copyrights
for details).
Submissions must be written by you, or copied from a public domain or similar free resource (see
AddOn Studio Wiki:Copyrights
for details).
Cancel
Editing help
(opens in new window)
Templates used on this page:
Template:Apinav
(
edit
)
Template:Editlink
(
edit
)
Template:Tocright
(
edit
)
Template:Wowlua
(
edit
)