Using arrays of vector3s to avoid new
I've seen a script that requires creating lots of temporary vectors each frame, and the author, to avoid using "new" all the time, instead had a large array of Vector3s and Vector2s. Every frame, he reset the pointer to the array back to 0 and incremented it each time he needed a new vector, before changing the vector's components.
My question: does this really provide any significant benefit?
It's a struct, so I can't imagine it's too helpful. Did the author of the code say otherwise?
I'm not sure I follow the reasoning behind "It's a struct...". Certainly reducing the amount of memory being allocated/deallocated each frame can lead to a performance benefit if those allocations are large enough. Using a pool of re-useable items can help, or using static variables in some instances is the way to go (not thread safe).
there's a very good unite keynote about performance optimation in the unity ressources: http://unity3d.com/support/resources/unite-presentations/performance-optimization
@flaviusxvii: structs like Vector3 are allocated on the stack, rather than the heap like classes. I'd guess that using a convoluted "array of Vector3s" scheme might actually result in worse performance. At least, it would be much more annoying code for no gain that I'm aware of.
At least in the old times (C, Pascal etc.), only temporary variables were allocated in the stack, because the stack frame was released on return, and everything in it was lost. Every non-temporary variable should be allocated in the heap or in the global data segment. Ok, there are a lot of new things in C# and other modern languages, but as far as I know the calling proccess is the same - a stack frame is allocated, the function is executed, and upon return the stack frame is released.
NOTE: Forgive me, @Eric5h5 - due to some inexplicable and stupid reason I was thinking about non-temporary arrays. You're right: simple temporary variables like Vector2 or Vector3 don't require memory allocation for their components. A more complex class could require memory allocation, thus consu$$anonymous$$g heap resoureces even if it was a temporary variable. And stack allocation is cheap (or free, to be more precise) - since there's no garbage collection (blocks are allocated and deallocated sequentially).
Answer by Eric5h5 · Jun 24, 2011 at 08:35 PM
It's not a good idea to do that, at least when it comes to structs like Vector3. Here's the result of a test involving 1000 instantiated objects. It uses a class that's essentially a Vector3, except it's a class and not a struct:
class Test {
var x : float;
var y : float;
var z : float;
function Test (x : float, y : float, z : float) {
this.x = x;
this.y = y;
this.z = z;
}
}
The script on each of the 1000 objects allocates a new Test class every frame in Update:
function Update () {
var foo = new Test(0.0, 0.0, 0.0);
}
As you can see, there are GC spikes, and it allocates 19.5 KB per frame. So, here's the result of a test that allocates a new Vector3 in Update:
function Update () {
var foo = new Vector3(0.0, 0.0, 0.0);
}
As you can see, there are no GC collection spikes, and no bytes being allocated per frame. It's perfectly OK to allocate new structs like Vector3 in Update. It is, in fact, preferable to the alternative, namely convoluted messy code that doesn't actually accomplish anything. Simply keep variables local as usual, and don't try any fancy schemes involving re-using array entries (unless you're dealing with classes and not structs, I guess).
Very interesting answer, good to know! For everyone who would like to read up on what a struct exactly is and how it differs from a class, this is a pretty good explanation http://msdn.microsoft.com/en-us/library/aa664471(v=vs.71).aspx
@Joshua interesting link. Although it doesn't support the assertions that classes and structs are allocated in different places in memory based on their type. But.. I'm being ignored, so no bother.
That's weird, the 1st screenshot isn't showing up anymore. In case this is happening for others, here are the screenshot links:
I'm still not convinced this test is even testing the right thing. I thought the question was about making an object pool vs. allocating on-the-fly. How is this even remotely addressing that?
@flaviusxvii You can't make an object pool if you aren't using objects.