Page 1 of 1

LuaTable.GetValue without GC

Posted: Sun Jun 11, 2017 5:21 pm
by alfonso
Hi Tony!,

I started recently with the optimization in the serialized system of the game, but i noticed that when I loop over the conversations to gets the values it's generate a lot of GC when i use GetValue over a LuaTable.

What is the best way to get a value without generete any GC or less if it is possible?

Thanks for all :)

Image

Image

Re: LuaTable.GetValue without GC

Posted: Sun Jun 11, 2017 8:55 pm
by Tony Li
Hi Alfonso,

Try the code below. It should generate almost zero garbage. It uses LuaInterpreter (Language.Lua) directly, and it runs the enumerator manually instead of using foreach, which can cause garbage collection due to boxing. I used the "Title" field in the example below because my test database didn't have a Count field.

Code: Select all

public void RunTest()
{
    var sb = new StringBuilder();

    // Get the Conversation[] table straight from the Lua environment:
    var conversationTable = Lua.Environment.GetValue("Conversation") as Language.Lua.LuaTable;

    // Loop through the table's list elements:
    // (Enumerate manually to avoid garbage)
    int idInList = 0;
    var conversationListEnumerator = conversationTable.ListValues.GetEnumerator();
    while (conversationListEnumerator.MoveNext())
    {
        idInList++;
        var fieldTable = conversationListEnumerator.Current.Value as Language.Lua.LuaTable;
        ProcessConversation(sb, idInList, fieldTable);
    }

    // Loop through the table's dictionary elements:
    // (Enumerate manually to avoid garbage)
    var conversationDictEnumerator = conversationTable.KeyValuePairs.GetEnumerator();
    while (conversationDictEnumerator.MoveNext())
    {
        var idKey = conversationDictEnumerator.Current.Key;
        var idInDict = (int)(idKey as Language.Lua.LuaNumber).Number;
        var fieldTable = conversationDictEnumerator.Current.Value as Language.Lua.LuaTable;
        ProcessConversation(sb, idInDict, fieldTable);
    }

    Debug.Log(sb.ToString());
}

void ProcessConversation(StringBuilder sb, int id, Language.Lua.LuaTable fieldTable)
{
    var enumerator = fieldTable.KeyValuePairs.GetEnumerator();
    while (enumerator.MoveNext())
    {
        var key = enumerator.Current.Key as Language.Lua.LuaString;
        if (string.Equals(key.Text, "Title"))
        {
           var value = enumerator.Current.Value as Language.Lua.LuaString;
            sb.AppendFormat("Conversation[{0}].Title = '{1}'; ", id, value.Text);
            break;
        }
    }
}
The way LuaInterpreter handles tables is a little confusing. If you add elements Conversation[1], Conversation[2], Conversation[3], in order, LuaTable will store them in a List for efficiency. But if you skip numbers -- Conversation[1], Conversation[4], Conversation[7] -- it can't store them in a list, so it stores the new elements in a Dictionary. But the old elements are still in the List. That's why the code above has to loop through the List and the Dictionary.

Re: LuaTable.GetValue without GC

Posted: Tue Jun 13, 2017 6:48 am
by alfonso
Thanks mate i will try them :)

Re: LuaTable.GetValue without GC

Posted: Tue Jun 13, 2017 7:44 am
by alfonso
Image
this is another thing :) thanks so much men!!!

Re: LuaTable.GetValue without GC

Posted: Tue Jun 13, 2017 8:25 am
by Tony Li
Happy to help!