Thread Tools Display Modes
04-26-07, 07:21 AM   #1
ProfOak
A Cyclonian
Join Date: Oct 2005
Posts: 47
Best way to make an optimized table

Hi!

Thank u 4 having to time to read my post :P

I have a question regarding the best way to create an optimized table.
My addon needs a table that will store massive info, so I was wondering which way is the best to keep the game flowing:

myTable = {};
myTable["Option1"] = value;
myTable["Option2"] = value;
...
myTable["OptionN"] = value;
...
myTable["AnotherOption1"] = value;
...

or

myTable = {};
myTable.Option = {};
myTable.Option[1] = value;
myTable.Option[2] = value;
...
myTable.Option[N] = value;
...
myTable.AnotherOption = {};
...

or is there another way ?

Thank U and Cheers

P.S. 'N' stands 4 a number ^^
  Reply With Quote
04-26-07, 08:22 AM   #2
Korred
A Flamescale Wyrmkin
Join Date: Dec 2006
Posts: 101
YOu could also do:

myTable.Option.Next = "yada"

I'm pretty sure this is the way that a majority of the mods do it. It's the preferred way I figure, I also don't think one way is any slower / faster than any other.
  Reply With Quote
04-26-07, 03:02 PM   #3
Shirik
Blasphemer!
Premium Member
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2007
Posts: 818
The second option you gave will typically be faster and more memory efficient, given that the key names don't really need a qualified name (if a number can represent it just as well). But you haven't given us nearly enough information to answer the question, there are a lot of factors. One other thing, however, to point out, is that Lua allocates tables in powers of two. Thus, a table with 10000 numerical indexes will take up the same size as one with 16300. So, if you can, try to use what you have. Table sizes 2, 4, 8, 16, 32, 64, 128, 256, etc., are all optimally-sized tables. Check this:

Code:
> collectgarbage"stop";
> a = {};
> gc = 0;
> for i = 1, 50000 do
>> a[i] = i;
>> if gc < collectgarbage"count" then
>> print(i..": "..collectgarbage"count");
>> gc = collectgarbage"count";
>> end
>> end
1: 28.58203125
2: 28.6552734375
3: 28.748046875
5: 28.8701171875
9: 30.056640625
17: 30.3837890625
33: 30.96484375
65: 32.0419921875
129: 34.123046875
257: 38.2041015625
513: 46.287109375
1025: 62.3681640625
2049: 94.453125
4097: 158.5302734375
8193: 286.6171875
16385: 542.6982421875
32769: 1054.787109375
__________________
たしかにひとつのじだいがおわるのお
ぼくはこのめでみたよ
だけどつぎがじぶんおばんだってことわ
しりたくなかったんだ
It's my turn next.

Shakespeare liked regexes too!
/(bb|[^b]{2})/

Last edited by Shirik : 04-26-07 at 03:05 PM.
  Reply With Quote
04-27-07, 06:41 AM   #4
ProfOak
A Cyclonian
Join Date: Oct 2005
Posts: 47
Let me thank u both 4 ur replys :P

Shirik, thank u 4 that detailed info concerning memory alocation.

The table I'm talking about is a dynamic 1, that will store some info regarding the mobs a char encounters along the way.
Since there are mobs w the same name but diferent levels, I was thinking to make something like

myTable = {};
myTable.Mob1 = {};
myTable.Mob1[10] = "info goes here"; -- 10 stands for mobs level
myTable.Mob1[15] = "info goes here"; -- 15 stands for mobs level
myTable.Mob2[-1] = "info goes here"; -- -1 stands for world boss level. no clue if it's possible to have it like that
myTable.MobN[N] = "info goes here";

Or if Korred's way is more optimal

myTable = {};
myTable.Mob1 = {};
myTable.Mob1.10. = "info goes here"; -- 10 stands for mobs level
myTable.Mob1.15 = "info goes here"; -- 15 stands for mobs level
but in this case '-1' might not work

I have no clue how many mobs there are or will be, so I really need the best way to make this functional.

Thank U :P
  Reply With Quote
04-27-07, 08:37 AM   #5
Korred
A Flamescale Wyrmkin
Join Date: Dec 2006
Posts: 101
In the case of dynamic creation like you're talking where I assume the first key is the mob name ie "Deviate Raptor" "Deviate Striker" or "Ragnaros" then where you have spaces you can't do dTable.Deviate Raptor, you can do dTable["Deviate Raptor"] if I remember correctly but again this isn't a prefered method. I would probably do a s/ /_/g and do dTable.Deviate_Raptor

I'm also not sure you can have a dTable.Deviate_Raptor.12, in my days of c++ and other said languages using numbers to start a label for a struct entry wasn't supported so I always prefixed a letter. In this case I would have done dTable.Deviate_Raptor.L12 or something to that effect. To deal with the boss it could be as simple as dTable.Ragnaros.Boss In most cases though you'll never have much more than a 2 or 3 level split between any given mob.

Would you mind if I ask what your idea is? Maybe we can give some more targeted answers in the realm of data storage and manipulation.
  Reply With Quote
04-27-07, 11:32 AM   #6
Shirik
Blasphemer!
Premium Member
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2007
Posts: 818
Correct, Kored, you can't:

Code:
> r = {}
> r[12] = 12;
> =r.12
stdin:1: '<eof>' expected near '.12'
Now, also note this: foo["bar"] and foo.bar are completely identical. It's up to you which way to use, but there is no benefit of one over the other (other than for readability purposes -- if you want to get more complicated, one method does imply something where the other does not with regards to OOP, but that's another story... if you want, read my article at http://www.wowwiki.com/Object_Oriented_Programming ).

Another thing to note is that if you are going to be skipping entries, you start using a hash table, not an indexed table. Thus:

Code:
> c = {}
> c[1] = 1;
> c[2] = 2;
> = #c
2
> c[10] = 10;
> = #c
2
> c[5] = 5;
> = #c
2
> c[4] = 4;
> = #c
10
> = c[6]
nil
So some strange things start happening Technically for these tables, the length operator # is undefined, but that's probably not your concern. What IS your concern is this:

Code:
> collectgarbage"stop"
> foo, bar, gc = {}, {}, 0 -- Allocate before counting GC
> gc = collectgarbage"count"
> for x = 1, 100 do
>> foo[x] = x;
>> end
> print(collectgarbage"count"-gc)
4.443359375
> gc = collectgarbage"count"
> bar[1] = 1;
> bar[100] = 100;
> for x = 2, 99 do
>> bar[x] = x;
>> end
> print(collectgarbage"count"-gc)
4.91015625
The tables are stored differently, and that's something you should keep in mind. Hash tables (which the becomes) are almost always bigger than indexed tables, so pay attention how you're creating the table. A lot of factors come into play. But Lua will always try to find the optimal way to create the table at the time, which may be an indexed table, depending on where you're doing it. Remember the powers of two? See:

Code:
> collectgarbage"stop"
> foo, bar, gc = {}, {}, 0
> gc = collectgarbage"count"
> for i = 1,16384 do
>> foo[i] = i;
>> end
> print(collectgarbage"count"-gc)
259.2587890625
> gc = collectgarbage"count"
> for i = 1,10000 do
>> bar[i] = i;
>> end
> bar[16384] = 16384;
> for i = 10001, 16383 do
>> bar[i] = i;
>> end
> print(collectgarbage"count"-gc)
261.029296875
vs.

Code:
> collectgarbage"stop"
> foo, bar, gc = {}, {}, 0
> gc = collectgarbage"count"
> for i = 1, 16384 do
>> foo[i] = i;
>> end
> print(collectgarbage"count"-gc)
259.26171875
> bc = collectgarbage"count"
> gc = collectgarbage"count"
> for i = 16384, 1, -1 do
>> bar[i] = i;
>> end
> print(collectgarbage"count"-gc)
258.7421875
> baz = {}
> gc = collectgarbage"count"
> for i = 1,16384,4 do
>> baz[i] = i;
>> end
> for i = 2,16384,4 do
>> baz[i] = i;
>> end
> for i = 3,16384,4 do
>> baz[i] = i;
>> end
> for i = 4,16384,4 do
>> baz[i] = i;
>> end
> print(collectgarbage"count"-gc)
266
So it can vary depending on when and how it's created. Always keep that in mind. And I'll shut up now, I think I've thrown too much information your way


EDIT: Not stopping GC produces strange results
__________________
たしかにひとつのじだいがおわるのお
ぼくはこのめでみたよ
だけどつぎがじぶんおばんだってことわ
しりたくなかったんだ
It's my turn next.

Shakespeare liked regexes too!
/(bb|[^b]{2})/

Last edited by Shirik : 04-27-07 at 11:48 AM.
  Reply With Quote
04-27-07, 06:13 PM   #7
ProfOak
A Cyclonian
Join Date: Oct 2005
Posts: 47
thank u all 4 the help

Will sure look @ the link u posted, shirik. gave it a quick look but @ the time I made this reply I was almost asleep on top of the keyboard. So, after a good night sleep, I shall look @ it w the attention it deserves

Regarding my question, 4 the time being, I'll use myTable["optionN"][N] (N stands for index).
This way i can keep info nicely organized like this:

myTable["option1"][1]
myTable["option1"][2]
myTable["option2"][1]
...
myTable["optionN"][N]

like u sayd korred, it's not possible to use the myTable.option denotation (or is conotation O.o ? lol @ my english) because of the spaces in 'option' part and myTable.option.N wasnt making much sense but post was made

Thank u all again 4 ur help and patience ^^
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Best way to make an optimized table


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