Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

UPDATE: This question refers to Farseer 2.x. The newer 3.x doesn't seem to do this.

I'm using Farseer Physics Engine quite extensively at the moment, and I've noticed that it seems to store a lot of temporary value types as members of the class, and not on the stack as one might expect.

Here is an example from the Body class:

private Vector2 _worldPositionTemp = Vector2.Zero;

private Matrix _bodyMatrixTemp = Matrix.Identity;
private Matrix _rotationMatrixTemp = Matrix.Identity;
private Matrix _translationMatrixTemp = Matrix.Identity;

public void GetBodyMatrix(out Matrix bodyMatrix)
{
    Matrix.CreateTranslation(position.X, position.Y, 0, out _translationMatrixTemp);
    Matrix.CreateRotationZ(rotation, out _rotationMatrixTemp);
    Matrix.Multiply(ref _rotationMatrixTemp, ref _translationMatrixTemp, out bodyMatrix);
}

public Vector2 GetWorldPosition(Vector2 localPosition)
{
    GetBodyMatrix(out _bodyMatrixTemp);
    Vector2.Transform(ref localPosition, ref _bodyMatrixTemp, out _worldPositionTemp);
    return _worldPositionTemp;
}

It looks like its a by-hand performance optimisation. But I don't see how this could possibly help performance? (If anything I think it would hurt by making objects much larger).

share|improve this question

3 Answers 3

up vote 6 down vote accepted

Although in .NET value types are stored on the stack, resulting in a minimal allocation cost, it does not however eliminate the cost of initialization.

In this case we have a set of functions using one or two temporary matrices, which would result in the initialization of 16-32 floats per call. While this may seem insignificant, if the methods are used often enough (say, thousands and thousands of times per frame), the total overhead can have a meaningful impact. If such a technique is used systematically across all such methods, the overhead eliminated can be considerable.

While use of such a technique eliminates the ability to provide thread safety at a per-object level, it is generally unwise to provide that guarantee at such a granular level.

share|improve this answer
    
Are you sure about that? One thought I had was that it might be to avoid calling constructors. But for value types you don't need to call a constructor - including the default parameterless constructor - if you're going to set all the members (or pass it as an out parameter). I'm fairly sure the entire point of this rule is so the compiler can skip zeroing that memory - right? (Is it really that slow to move the stack pointer?) –  Andrew Russell Jul 18 '10 at 6:29
    
Surprising, no? Unfortunately, if you inspect the generated IL, the temporary matrices are initialized. A few quick tests show the member-temp version is ~10-15% faster. –  Jason Kozak Jul 18 '10 at 14:43
1  
I am stunned. In "Understanding XNA Framework Performance" (GDC2008) Shawn Hargreaves says of structs: "[the JIT] will usually figure out: 'in the next line he immediately sets all three fields [of the Vector3], so I don't even need to initialize it to zero'". Which is where my info is coming from. But on listening again now, he only says "usually". The immediate next point in the presentation is that the JIT behaves differently with the debugger attached, affecting performance (how did you test?). Also: he is talking about the JIT here, so perhaps the IL stays "nice" (verifiability?). –  Andrew Russell Jul 18 '10 at 15:14
    
The IL was inspected via Reflector, and the tests were run outside the IDE built in Release (on Windows, I no longer have a CC membership to test against) –  Jason Kozak Jul 18 '10 at 15:29
1  
Based on this - I wonder if it would be better (and how much better it would be) to make those member-temporaries static (and/or more aggressively reuse them). As it is, just for example, the Body class in Farseer has some 73 floats worth of "unnecessary" members. –  Andrew Russell Jul 19 '10 at 10:02

Good question. I'm a pretty sharp C#/.NET guy and a bit of a performance nut, and this seems like a rather odd design decision to me. The first thing that jumps out at me is that this code is in no way thread safe. I don't know if that's an issue in a Physics system, but storing temporary data outside the scope of a method is often a recipe for disaster.

Honestly, if I regularly encountered this kind of code in a third-party framework, I would probably try to find another framework.

share|improve this answer
3  
Doesn't really answer the question. –  Brian Ortiz Jul 16 '10 at 19:29
    
Yeah, the best I could do is confirm that he's not crazy, and there doesn't seem to be any real benefit it being coded that way. The only find out the true intent is to ask the guy who wrote the code :). –  Mike Strobel Jul 17 '10 at 1:27
    
Thanks, Mike. I'm beginning to suspect that the original developer is the crazy one, not me. But it always helps to check ;) –  Andrew Russell Jul 17 '10 at 2:34
    
Thread safety can sometimes be a costly guarantee to provide, especially when writing a FP computation heavy library for a platform that doesn't make use of SIMD instructions. –  Jason Kozak Jul 17 '10 at 15:13

The GC on the 360 basically only does GEN 2 collections, which are expensive, so temporary variables that get created and removed every frame (like temp objects) cause a whole collections to run, which will kill performance really fast.

I suspect they did it this way to reuse that object and not have it collected.

share|improve this answer
1  
This occurred to me as well, but the temporary members appear to be value types, so they wouldn't be allocated on the managed heap anyway. –  Mike Strobel Jul 16 '10 at 16:15
2  
Right, but only if they are class members. If they are locals (method-scoped), they would be allocated on the stack. The question is why they they didn't simply go that route. –  Mike Strobel Jul 16 '10 at 19:22
1  
@Blair - According to MSDN (msdn.microsoft.com/en-us/library/bb203912.aspx) the Xbox360 uses the .NET Compact Framework. It seems that the difference in GC is related to that, so I'd pursue that for further research on the matter. –  Logan Kincaid Jul 17 '10 at 3:04
1  
@Blair: @Logan Kincaid is correct. The CF's Garbage Collector behaves differently than the regular framework's. There's a good talk on the subject in XNA Game Studio 3.0 Unleashed - however that book will soon be outdated with the release of 4.0. –  SnOrfus Jul 17 '10 at 5:17
1  
@Blair: Due to the limited memory environment of the 360 (and most devices targeted via the CF), a Mark & Sweep GC is used. As a result, lots of small allocations will trigger a collection, and collection time is relative to the # of references. Lots of details here: download.microsoft.com/.../Mobility/… –  Jason Kozak Jul 17 '10 at 15:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.