|
Looking at the implementation of table.concat, what seems to
happen is that Lua uses a buffer for the result which presumably
grows exponentially with powers of two (hence leading to twice the
memory usage). I could see a minor point being made for this since
coercion requires table.concat to handle numbers; to "act wisely"
it'd have to stringify these numbers, count the bytes, then
stringify them again when writing to the buffer. Using a dynamic
buffer it only has to stringify the numbers once.
Hi!
I'm trying to concatenate huge strings using table.concat()
local n=7
collectgarbage()
local a = { ("a"):rep(2^30) }
for j = 2, n do
a[j] = a[1]
end
local b = table.concat(a)
print("GBytes used:", #b/2^30, collectgarbage("count")/2^20)
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.
Contrary to my expectation, on a 16 GB RAM Linux machine: n=7 works OK, but n=8 starts eating swap space.
It looks like table.concat temporarily uses twice more memory than it is actually needed for a clever concatenation.
Unlike table.concat, the usual Lua concatenation operator does not have this problem. It may be used as a workaround, but it is limited by the number of VM registers.