lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

2017-12-01 0:38 GMT+02:00 Soni "They/Them" L. <>:

> I have some code that looks like this:
> debug.setmetatable("", {__index=function(o,k)
>   local mt = metatables[coroutine.running()].string
>   if mt then
>     local __index = rawget(mt, "__index")
>     if type(__index) == "function" then
>       return __index(o,k)
>     else
>       return __index[k]
>     end
>   end
>   error()
> end})
> It takes the metatables for the basic Lua types (string, number, nil, etc)
> and replaces them with a proxy metatable. This proxy metatable forwards to a
> different table based on the currently running coroutine. This gives me
> virtualization of those metatables.
> It's really slow (3-4x slower[1] than the default string metatable) and I'd
> like to make it faster. Is that possible?
> [1] - I haven't actually benchmarked it, but default string metatable gives
> about 2 table accesses per operation; this thing does at least 8 when using
> globals, and that doesn't take into account interpreter overhead and all the
> function calls!

Not quite sure this is very strongly related to what you ask ... but I recently
coded a package for a data structure rather like XML: a container for named
attributes and a list of objects, in which each object is again a container for
attributes and a list of objects, etc. There are more than 100 variations of
object. Each record knows its parent and its outer container and has
an attribute 'tag' identifying what kind of record it is.

I started off with only one class, then had a class for every variation, then
grouping them into about five classes, and finally settled on only two
classes: one for outside containers and one for inner objects at whatever
level. There are thus only two metatables, let's call them Object and Record.

Record.__index is a function that at some stage looks for stuff
in META[tag], where META is an upvalue whose pairs are tables
keyed by the possible values of 'tag'.

If I needed to switch all the metatables in one go, META could be a field
in the outside container instead of an upvalue.