Is there a reason not to include the ability to read the number of
uservalues associated with a userdata
(lua_getiuservalue()/lua_setiuservalue()) into the API? That would
allow a slightly more efficient tuple implementation, among other
A sizeof(unsigned short), and possibly more, could be saved if it
didn't have to store the uservalue count.
Other things would mostly be debugging-related (though performance
would then be irrelevant).
I'm inspecting efficiency of different ways of storing a possibly
variable number of arguments. Options considered:
t1: create a single table, fill in place;
u1: create a single tuple, fill in place;
tN: create a new table every time;
uN: create a new tuple every time;
t0: create a single table, assign using a,a,a=...
(effectively cheating as this limits argument count)
One possibly useful thing I can share is the benchmark result set of
these options (4 elements actually assigned, 1 mln loop iterations,
median of 10, MIPS, somewhat patched Lua 5.4.0):
As you see, tuples beat tables if we (have to) create a new one every
time; tables beat tuples when they can be reused (assignment performed
via lua_rawseti in a loop vs lua_setiuservalue in a loop). The
"cheating" variant is there to provide a baseline to compare against.
Roberto Ierusalimschy <[hidden email]>:
> > Is there a reason not to include the ability to read the number of
> > uservalues associated with a userdata
> > (lua_getiuservalue()/lua_setiuservalue()) into the API?
> No specific reason except the usual (to avoid bloating the API with
> functions seldom used.)
Speaking of which, it looks like luaL_checkudata/luaL_testudata are
quite often used, but also quite inefficient (if the rest of the
method runs fast), which seems to cause the somewhat strange benchmark
results I sent earlier. It looks up a metatable by name, then it gets
the actual one, compares them and pops both. Tuple-related benchmarks
look much better if I drop the metatable check.
A more efficient lower-level API could be, say, lua_testmetatable(L,
idx_tested, idx_of_metatable) which would return e.g. 1 if the value
at the idx_tested index has the metatable supplied at idx_of_metatable
(all done via pointer comparisons, no metatable pushing/popping), 0 if
it has no metatable at all, and -1 if it has a metatable but it's
different from the supplied one. The method would have the expected
metatable as an upvalue.