Sometimes there is a faster way. First let’s look at a simple append one table to another:
For In loop (slowest) 100%
local t1 = {string.byte(string.rep('A',256),1,256)}
local t2
for x = 1, 1000 do
t2 = {1,2,3,4,5,6,7,8,9,0}
for _, v in pairs(t1) do
table.insert(t2, v)
end
end
Regular For Loop (slightly faster) 84.3%
local t1 = {string.byte(string.rep('A',256),1,256)}
local t2
for x = 1, 1000 do
t2 = {1,2,3,4,5,6,7,8,9,0}
for v = 1, #t1 do
table.insert(t2, v)
end
end
log(#t1..' : '..#t2)
table.move (much faster) 24.5%
local t1 = {string.byte(string.rep('A',256),1,256)}
local t2
for x = 1, 1000 do
t2 = {1,2,3,4,5,6,7,8,9,0}
table.move(t1,1,#t1,#t2+1,t2)
end
log(#t1..' : '..#t2)
Table.unpack (fastest) 12.5%
local t1 = {string.byte(string.rep('A',256),1,256)}
local t2
for x = 1, 1000 do
t2 = {1,2,3,4,5,6,7,8,9,0, table.unpack(t1)}
end
log(#t1..' : '..#t2)
Test are based on ETC Mosaic v 2.14.4 soft triggers running scripts:
Results:
for in 1,213,051 microseconds
for 1,022,291 microseconds
move 296,931 microseconds
unpack 151,784 microseconds
The next test is extracting a zero terminated string from a buffer
buffer = {
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,0,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,
1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9,1,2,3,4,5,6,7,8,9,9}
String Concatenate (slowest) 100%
local str = ''
local i
for x = 1, 1000 do
i = 1;
str = ''
local len = #buffer
while buffer[i] ~= 0 and i<=len do
str = str .. string.char(buffer[i])
i = i + 1
end
end
Scan and copy (faster) 10%
local str = ''
local i
for x = 1, 1000 do
i = 1;
local len = #buffer
while buffer[i] ~= 0 and i<=len do
i = i + 1
end
str = string.char(table.unpack(buffer,1,i))
end
table.unpack / string:unpack (fastest) 6.6%
local str
local i
for x = 1, 1000 do
local sbuffer = string.char(table.unpack(buffer)) -- second copy
str, i = string.unpack('z' , sbuffer) -- final copy
end
Results:
string concatenate: 3,114,018 microseconds
scan and copy: 308,604 microseconds
table.unpack / string.unpack: 207,526 microseconds
The final test is float32 extraction
Native Lua code (slowest) 100%
buffer = {0x43, 0x68, 0x61, 0x6E}
local float
for x = 1, 10000 do
local sign = 1
local mantissa = (buffer[i+1] & 127)<<16 | buffer[i+2]<<8 | buffer[i+3]
if buffer[i] > 127 then
sign = -1
end
local exponent = (buffer[i] & 127)<< 1 | (buffer[i+1]>>7)
if exponent == 0 then
float = 0.0
else
mantissa = (math.ldexp(mantissa, -23) + 1) * sign -- ldexp is deprecated in Lua 5.3 -> replace ldexp(x, exp) with (x * 2.0^exp)
float = math.ldexp(mantissa, exponent - 127)
end
end
string.unpack() (fastest) 91%
buffer = {0x43, 0x68, 0x61, 0x6E}
local float
for x = 1, 10000 do
local b = string.char(table.unpack(buffer,1,4))
float = string.unpack('>f', b)
end
Results:
Native Lua Code: 120,978
string.unpack: 110,149