lua-users home
lua-l archive

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


Robert G. Jakabosky <bobby <at> sharedrealm.com> writes:
> How about something like this?

That turned out to be pretty slow (LuaJIT can't generate code for
the string concatenation in the inner loop yet, so the trace kept getting
aborted) but your approach got me to thinking and I came up wit this,
which turns out to be extremely fast:

local ffi = require("ffi")

ffi.cdef[[
  struct MyType { bool has_a, has_b;  int a, b; };
]]

function MyStructure()
  local cdata = ffi.new("struct MyType")
  local self = newproxy(true)
  local meta = getmetatable(self)
  local newindex_tab = {
    a = function(value)
      cdata.a = value
      cdata.has_a = true
    end
  } 
  function meta:__newindex(key, value)
    newindex_tab[key](value)
  end
  return self
end

wrapped = MyStructure()
before = os.clock() 
for i=1,50000000 do wrapped.a = 5 end
print(string.format("50,000,000 assignments took %.2f CPU seconds",
                    os.clock() - before))

It turns out that table lookup inside __newindex is basically free, as are
both of the function calls: in my benchmark calling "wrapped.a = 5" was
just as efficient as calling the cdata cirectly!  The generated assembly is
longer, but it runs at the same speed.  Amazing.

It's tempting to be worried that these results won't hold up if ie. I add a lot
more entries to newindex_tab, or if the program is a lot larger and has more
complicated control flow.  But for the moment it looks like I can use __newindex
and get just the same performance as if I was just using function calls.

Josh