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.
No comments yet.
