lua-users home
lua-l archive

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


Hi,

Currently, as I understand it, the metatable of a Lua value is a Lua table with string keys "__index", "__add", "__tostring", etc. These string keys are stored in a hash table and incur a hash-table lookup whenever accessing a metatable, i.e., if I write something like

t = {}
setmetatable(t, {__index = {a = function() return "b" end}})

then upon calling t:a(), Lua will perform three hash-table lookups: one check for 'a' in 't', one check for __index in t's metatable, and finally a check for 'a' in the method table.

But accessing __index by a string lookup in a hash table seems unnecessarily complicated, when for metatables we are always interested in the same 20 or so keys. Instead, Lua could simply define global values:

__index = 1
__newindex = 2
__tostring = 3
-- and so on

and then we write the metatables like this:

t = {}
setmetatable(t, {[__index] = {a = function() return "b" end}})

Now we have exchanged a hash-table lookup for an array lookup. The code is not really more complicated; you have to type only two more characters. Plus, many people will use an OOP library that abstracts away the whole metatable creation, so they wouldn't notice any difference. Practically everything using metatables immediately gets faster. Other than backwards compatibility, I'm having trouble thinking of a downside.

In fact, if I understand correctly, Lua already stores a list of metatable keys, looks up the key by an index, and then does a hash lookup for that key in the metatable:

const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
  Table *mt;
  /* define mt (omitted for brevity) */
  return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}

Obviously the last line should be faster if it were just:

return (mt ? luaH_getint(mt, event) : luaO_nilobject);

...right?

Best,
Mason