This means we often want to decide whether a table is a sequence.
- Lars
Footnotes:
[1]: https://github.com/mlua-rs/mlua/issues/640
[2]: Benchmarking the following code against the equivalent code
with the is_sequence call removed, I can measure a ~2x speedup on
Lua 5.4.7; and even on LuaJIT, the version without is_sequence is
~1.3x faster. Clearly no blanket statement along the lines of
"checking whether a table is a sequence has negligible cost" can
be made, even in Lua, even if you do linear time operations on the
table. And mind you, my proposal is primarily about processing
Lua-provided tables in a systems programming language, though
there would also be potential merit for a Lua library function as
an aside. Unsurprisingly, an entire second iteration of a table -
with non-negligible work per iteration - comes at a cost. How much
cost remains with a Lua-provided API function would remain to be
seen, but I'm fairly sure there could be significant speedups in
some cases.
local function is_sequence(t)
local len = #t
local got = 0
for k in pairs(t) do
if type(k) ~= "number" or k < 1 or k > len or math.floor(k) ~= k then
return false -- strict check: don't want any extra keys
end
got = got + 1
end
return got == len
end
local function tmin(t)
assert(is_sequence(t)) -- remove this
local min = 0
for i = 1, #t do
min = math.min(min, t[i])
end
return min
end
local t = {}
local j = 1
for i = 1e6, 1, -1 do
t[j] = i
j = j + 1
end
print(tmin(t))
[3]: I would have provided a patch myself, but I've read that the
Lua team does not accept patches. It's just a simple utility
function that is barely coupled with the rest of the codebase,
except of course slightly with the table representation (but that is
unlikely to change substantially and if so, the function is easy to
update).To be clear, in my case, the json.{encode,decode} functions are implemented in C/C++. I disabled inlining for the respective function, attached a debugger, and after ~10s of intensive work, I checked the profiler stats.
-- Sainan
--
You received this message because you are subscribed to the Google Groups "lua-l" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lua-l+un...@googlegroups.com.
Okay, but that's not a contiguous table in whole, so it's irrelevant if the index assumption breaks, we need to return false anyway. -- Sainan
For randomly ordered valid sequences this assumption also fails, idk if that's a usecase to be considered.
-- test.lua
local M = 5000
local function test(n)
local indicies = {}
for i = 1, n do
indicies[i] = i
end
local res = { }
for i = 1, n do
local index = table.remove(indicies, math.random(1, #indicies))
res[index] = index
end
assert(#res == n)
for i = 1, #res do assert(res[i] == i) end
local i = 0
for k in pairs(res) do
i = i + 1
assert(k == i, string.format("#res = %d inconsistent key i=%d k=%d", #res, i, k))
end
end
for i = 1, M do
test(i)
end
-- bash
$ lua test.lua
test.lua:23: #res = 10 inconsistent key i=9 k=10
stack traceback:
[C]: in function 'assert'
test.lua:23: in local 'test'
test.lua:28: in main chunk
[C]: in ?
-- Sewbacca
local num, max = 0, 0
for k in pairs(t) do
if type(k) ~= 'number' or k < 1 or not is_int(k) then return false end
num = num + 1
if k > max then max = k end
end
return max == num
For a faster rejection, you might wanna add len = #t
and in the body check if k > len then break end
-- Sewbacca
Damn, a breaking change in Lua 5.5. Well, maybe something to consider before upgrading.
-- Sainan