lua-users home
lua-l archive

Re: Index with multiple parameters?

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


> This is exactly the problem I'm trying to avoid. The problem is when
> you call this millions of times you get millions of temporary objects.
> It's slow (lots of memory allocation) and causes garbage collector
> thrashing.
> 
> Technically with that same approach it can look "proper":
> 
> vertex_vector[20].x = 2.5
> 
> It's the same problem though with needing temporary objects.
Along these lines, have you tried caching temporary objects? You could use
something like this quick prototype:
-- vector.lua
local getmetatable, assert = getmetatable, assert
local newproxy, ipairs = newproxy, ipairs
local getfenv, setfenv = debug.getfenv, debug.setfenv
module(...)
local ud = {} -- cache userdata
local function register (d)
 local r = ud[d]
 if r == nil then
 r = newproxy(true)
 -- fill metatable
 local m = getmetatable(r)
 m.__index = function(u, k)
 local e = getfenv(u)
 local l = e._level
 local t = d[l]
 assert(t[k] ~= nil, "invalid key")
 local v = e[k]
 if v == nil and l < #d then
 v = new(d, l + 1)
 e[k] = v
 end
 return v
 end
 m.__newindex = function(u, k, v)
 local e = getfenv(u)
 local l = e._level
 assert(l == #d, "invalid level for assignment")
 e[k] = v
 end
 -- cache
 ud[d] = r
 end
 return r
end
function new (d, l) -- d is dimension table, l is level
 local l = l or 1
 local t = {_level = l}
 local u = newproxy(register(d))
 return setfenv(u, t)
end
-- utils
function range (f, t) -- from, to
 local r = {}
 for i = f, t do r[i] = true end
 return r
end
function labels (t)
 local l = {}
 for _, v in ipairs(t) do l[v] = true end
 return l
end
[ Test ]
$ lua -lvector
Lua 5.1.2 Copyright (C) 1994-2007 Lua.org, PUC-Rio
> u = vector.new{vector.range(1, 20), vector.labels{"x", "y", "z"}}
> print(u[20].x); u[20].x = 2.5
nil
> u[1].y = 1; print(u[20].x + u[1].y)
3.5
Of course, you have to provide your userdata to "new" at the first level and
use customized getters/setters in __index and __newindex. If GC is still an
issue, you could follow Diego's suggestion in the "high performance math"
thread earlier and use lightuserdata.
Cheers,
Luis.
-- 
A mathematician is a device for turning coffee into theorems.
 -- P. Erdos 
-- 
Luis Carvalho
Applied Math PhD Student
Brown University

AltStyle によって変換されたページ (->オリジナル) /