lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



On Mon, Jul 18, 2022 at 4:27 AM Egor Skriptunoff <egor.skriptunoff@gmail.com> wrote:
I expect table.concat to act wisely:
it should calculate the result string length, allocate its memory and fill it with the result content.
So, for concatenating n copies of 1GB-string only (n+1) GBytes of memory would be needed:
1 GByte for the source string and n GBytes for the result string.

Consider this little gem:

local last_key = -1

local meta = {
    __index = function(meta, key)
        if key > last_key then
            last_key = key
            return "a"
        else
            return "bb"
        end
    end,
}

local t = setmetatable({}, meta)

print(table.concat(t, "", 1, 0x1 << 30))

If table.concat makes two passes over the array its estimate for the length is all wrong, and the contents will be different.
If table.concat makes only one pass and stores an intermediate array of string values it'll end up allocating a huge array relative to the size of the resulting string. In either case you lose.

table.concat could check for the presence of an __index method and be more clever about it, but that adds complexity to handle your edge case. My point is that this could be fixed, but it's complicated and table.concat would be slightly slower in the common case.

--