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