Frank’s Weblog

Old enough to know better, young enough to not care

Optimizing memory usage in LUA

Couple of days ago I received a message on curse.com about the memory usage of UberInventory. The general statement was that UberInventory uses a lot of memory. We were aware of this issue, but we had never given it much attention. But after this message we could ignore it no longer.

We have been reading several articles on the internet on how to optimize memory usage, performance and garbage collection using LUA. All those documents basically state that using locals as much as possible improves performance when accessing data structures and when storing a lot of data most of the times it is better to create larger tables instead a lot of smaller tables. This some times leads to a little more unreadable data structures but it keeps garbage generation to a minimum and less memory is needed to store the data.

Since UberInventory contains a lot of static data (pricing and recipe data) our first focus was to see if and how we could optmize those data structures.

The following results have been generated using LUA 5.0.1 and we have used the gcinfo() function to produce the numbers.

Orignal version of UberInventory_prices.lua

Dynimac
Memory
Garbage
threshold
Before 1531 3062
After 4189 6124
Delta 2658 3062
UBI_Prices = {
 [25] = {nil,7},
 [35] = {nil,9},
 [36] = {nil,7},
};

Modified version of UberInventory_prices.lua

Dynimac
Memory
Garbage
threshold
Before 1060 2121
After 2500 2121
Delta 1440 0
UBI_Prices_Buy = {
 [38] = 1,
 [39] = 5,
 [40] = 5,
};
UBI_Prices_Sell = {
 [25] = 7,
 [35] = 9,
 [36] = 7,
};

As you can see with the modified version there is big drop in the total memory that is needed to store the data and the structure does not create any additional garbage.

Changes made to UberInventory_prices.lua

  • Split data into two tables, one for buy prices and one for sell prices

Original version of UberInventory_recipes.lua

Dynimac
Memory
Garbage
threshold
Before 961 1921
After 3160 3842
Delta 2199 1921
UBI_Creatures = {
 [66] = { name='Tharynn Bouden', area='Elwynn Forest' },
 [340] = { name='Kendor Kabonka', area='Stormwind City' },
 [450] = { name='Defias Renegade Mage', area='Westfall' },
};
UBI_Quests = {
 [22] = { name='Goretusk Liver Pie', area='Westfall' },
 [38] = { name='Westfall Stew', area='Westfall' },
 [90] = { name='Seasoned Wolf Kabobs', area='Duskwood' },
};
UBI_RecipeDrops = {
 [4213] = { {8716,1}, {12396,1} },
 [4408] = { {7800,1} },
};

Modified version of UberInventory_recipes.lua

Dynimac
Memory
Garbage
threshold
Before 636 1272
After 1230 1272
Delta 594 0
UBI_Creatures = {
 [66] = 'Tharynn Bouden|Elwynn Forest',
 [340] = 'Kendor Kabonka|Stormwind City',
 [450] = 'Defias Renegade Mage|Westfall',
 [590] = 'Defias Looter|Westfall',
};
UBI_Quests = {
 [22] = 'Goretusk Liver Pie|Westfall',
 [38] = 'Westfall Stew|Westfall',
 [90] = 'Seasoned Wolf Kabobs|Duskwood',
};
UBI_RecipeDrops = {
 [4213] = { '8716:1', '12396:1' },
 [4408] = { '7800:1' },
};

Here you see the same results, huge drop and no garbage. These changes combined resulted into a decrease in memory of between 2 and 3 MB just for the static data.

Changes made to UberInventory_recipes.lua

  • For creatures and quests combine the name and area into one text field instead of using a table structure
  • For drop info combine mob id and drop rate into one text field instead of using a table structure

All the changes described in this post are implemented for UberInventory 1.6.

The next step will be digging into the data structures of the dynamic data stored within UberInventory.lua (WTF\Account\…\SavedVariables) and optimize those for memory usage and garbage.

January 19, 2009 - Posted by fmeus | UberInventory, World of Warcraft, lua | | No Comments Yet

No comments yet.

Leave a comment

You must be logged in to post a comment.