lua-users home
lua-l archive

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


Josh Haberman wrote:
> I know metamethods for ctypes are a TODO, but I was just wondering if
> the __gc metamethod is one of the ones that will be supported?  Or
> whether there's some reason why this would not be possible.

http://lua-users.org/lists/lua-l/2011-01/msg01217.html

> 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

Ouch! You're creating a different metatable, another table and two
different closures for every single instance. This is rather
wasteful. And it makes the compiler very unhappy when you need to
handle different instances with the same piece of code.

Instead create the userdata from C code and keep the cdata _inside_
the userdata. Cast the userdata to a pointer to your struct before
using it: http://lua-users.org/lists/lua-l/2011-01/msg01282.html

Important: create the metatable and its metamethods once and reuse
the _same_ metatable for _every_ instance.

> 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.

Because dead-store-elimination hits and turns your code into an
empty loop. This kind of benchmark is rarely helpful. :-)

--Mike