[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: LuaJIT with vectors
- From: Niklas Frykholm <niklas@...>
- Date: Thu, 18 Nov 2010 15:04:11 +0100
On Thu, Nov 18, 2010 at 11:40 AM, Mike Pall <email@example.com> wrote:
Petri Häkkinen wrote:Well, I disagree. There are other ways to eliminate allocations.
> Just to be sure that we're on the same page; I think vectors should be like
> other atomic data types, e.g. like numbers, rather than being objects. This
> would eliminate the allocation cost altogether.
Proper API design (pass a reference to a destination vector)
and/or adding escape analysis to the compiler will solve this in
My experience (having written two game engines with full Lua integration) is that if you do Vector3s the straightforward way as full user data, with a + b allocating a new Vector3 on the heap to return the result, you will see a noticable performance hit in Vector3 allocation and gc. Even if you use lua for just the high level stuff, you still tend to end up with lots of vector manipulation, fetching the position of objects, etc.
I've investigated some solutions:
* Vector3 in Value struct -- not very good, the memory increase is bad for consoles where you have a strict memory budget. And as Mike says, today performance is often limited by memory bandwidth, so this will hurt your performance as well.
* Pass by reference -- the lua programmer has to allocate all vectors explicitly and use pass-by-reference to modify them. This means that something like:
self.dir = (to - from):normalize()
will have to be rewritten as:
self.dir = Vector3.new()
local dist = Vector3.new()
Vector3.sub(to, from, dist)
This is certainly doable, but not a lot of fun for the lua programmers. You have to decide if you can live with this or not.
* Vector3 scratchpad -- temporary vectors are allocated from a scratchpad buffer that gets cleared every frame. They are represented in lua as lightuserdata. If you want to keep a Vector3 around for the next frame you need to explicitly box it in a full userdata object:
self.dir = Vector3Boxed.new()
self.dir:box( (to-from).normalize() )
This is the solution I am using right now. It kind of works but it is by no means ideal. Boxing and unboxing values means some busywork for the lua programmers. If they save a Vector3 without boxing it, they will get unexpected results. If they do too many operations in one frame, the scratchpad buffer will overflow.