End users shouldn't have to rewrite XNA math functions in order to improve performance.
- The overhead of passing a 64 byte Matrix by value is significant. Most especially when you are comparing two matrices for equivalency (==), or performing a Vector*Matrix multiplication (Vector3.Transform(Matrix)).
The following matrix comparison function performs 5-10 times better than your built in == comparison. If the matrices are equal, then it is about 5 times faster. If they are unequal then it fails fast, and is about 10 times faster.
public static bool Equals(ref Matrix a, ref Matrix b)
{
// i check the diagonal first for quick fails
return a.M11 == b.M11
&& a.M22 == b.M22
&& a.M33 == b.M33
&& a.M44 == b.M44
&& a.M12 == b.M12
&& a.M13 == b.M13
&& a.M14 == b.M14
&& a.M21 == b.M21
&& a.M23 == b.M23
&& a.M24 == b.M24
&& a.M31 == b.M31
&& a.M32 == b.M32
&& a.M34 == b.M34
&& a.M41 == b.M41
&& a.M42 == b.M42
&& a.M43 == b.M43;
}
It's faster simply because it passes the Matrices by reference, whereas the == operator passes both matrices by value:
public static bool operator ==(Matrix a, Matrix b)
That's a copy of 128 bytes of data, before we even check the first element!
Please confirm that you plan on providing "by ref" methods like this in addition to the very handy (if inefficient) current members.
btw- good job on the API overall guys. Especially you Tom Miller. Getting past the MS bureacracy in order to make something cool is not easy. I know. Kudos.
All Replies
I understand your point, and I agree 100%. However, I don't think this is yet the time to worry about performance. The age old axiom of make it work then make it fast is a good thing. I hope by final release they add optimized options but right now I don't think it should be the focus. This is doubly true given XNAs focus on Indy and beginning developers, which actually adds a 3rd aspect to that equation. Make it work, make it easy, then make it fast.
I love the simplicity of XNA as it stands now ( minus the bits that dont work right, or lack of content pipeline! :D ) and I dont want to see that prematurely fouled by early optomizations.
However, if at release the glaring performance flaws still exist, ill join you in the revolution!!! ;)
- Hmmm, I always assumed that using 'ref' would lead to the value types being boxed first, and thus would be slower. In fact I've just looked at the MSIL for the test case above, and it does box the values. If your timings are correct then I can only assume that the Jitter is somehow optimising that away, but I've never heard of that happening before!
- AndyL- There is no "box" when using the "ref" keyword. Which IL instruction are you interpreting as a "box" instruction?
Seraph- This is a "design philosophy" issue that should be addressed now. XNA is not just a fun little toolkit for beginners to write sprite based games. Many serious game developers want to use this for state of the art games. If the developers take advantage of what the language provides then this will be much easier.
C# IS as fast as C++ IF you take advantage of what the language provides.
I guarantee that pretty much all of the XNA authors are former C++ coders who wouldn't dream of passing a 64 byte struct to a C++ method by value.
What suddenly makes it ok to do it in C#?
Here is the Direct3D Vector Transform method:
D3DXVECTOR4 * D3DXVec4Transform( D3DXVECTOR4 * pOut, CONST D3DXVECTOR4 * pV, CONST D3DXMATRIX * pM );
Check thru all the Direct3D Math api's, and you will find that they only pass large structures by reference.
Is there really any good reason why we can't have C# methods that perform just as well? That's all I'm asking for, and that requires using the ref keyword when passing matrices (and Vectors). No, as I understand it, using ref will only result in boxing if the type is a value type( not derived from type object ). This means int will result in boxing as would any struct, but any non struct object would not be boxed. In that case, passing it by ref should be almost identical to the C++ world of passing by reference, meaning the reference itself sits on the stack, but points to memory on the heap ( whatever the hell that actually means in managed world ).
Structs are an exception, as I believe they are basically light weight classes ( with limits ) that exists solely on the stack. Thus, when passed by reference they need to be boxed. It also means that passing objects via ref is actually better from a performance perspective, assuming the object is of a sufficent size to see a gain.
Granted, this is all C# 1.0 based knowledge, if things have changed in the last few versions, I apologize.
Jurak wrote: AndyL- There is no "box" when using the "ref" keyword. Which IL instruction are you interpreting as a "box" instruction? As I said above, that isnt strictly true. Intrinsic types and structs are boxed when passed by reference. Unless, like I said earlier, this was changes with C#2 or C#3.
Jurak wrote:
Seraph- This is a "design philosophy" issue that should be addressed now. XNA is not just a fun little toolkit for beginners to write sprite based games. Many serious game developers want to use this for state of the art games. If the developers take advantage of what the language provides then this will be much easier.
C# IS as fast as C++ IF you take advantage of what the language provides.
I guarantee that pretty much all of the XNA authors are former C++ coders who wouldn't dream of passing a 64 byte struct to a C++ method by value.
What suddenly makes it ok to do it in C#?
Here is the Direct3D Vector Transform method:
D3DXVECTOR4 * D3DXVec4Transform( D3DXVECTOR4 * pOut, CONST D3DXVECTOR4 * pV, CONST D3DXMATRIX * pM );
Check thru all the Direct3D Math api's, and you will find that they only pass large structures by reference.
Is there really any good reason why we can't have C# methods that perform just as well? That's all I'm asking for, and that requires using the ref keyword when passing matrices (and Vectors).I think you misunderstood me. I agree with you on this point. I just think at this point in the beta is the wrong time to address performance issues, especially performance issues at the sake of complexity. There are so many things in XNA that need to be fixed or added, that I dont think performance should be the primary concern.
I understand the C# can be damned near as fast as C++, and I would love to see XNA go a long way towards smashing down the irrational bias against C#. That said, I think your estimates that "pretty much all" XNA authors are former C++ coders is most likely wrong... this coming from a C++ programmer! Many of the C++ coders are probrably ignoring XNA as they are working for major dev houses and are still using the XDK and C++ to create games. That leaves two groups, C++ programmers who are writing small or indy games who jumped on XNA as an opportunity to develop on a console ( for the first real time, ignoring the Net Yaroze from sony ) and the demographic that has always wanted to write games but were daunted by the process. I imagine you would find atleast a 50/50 split between the two camps.
- Serapth- Your understanding of "boxing", "structs", "references" and "values" within the .Net CLR framework is incorrect.
1. Boxing only occurs when a struct is assigned to a "reference" type variable. (such as "object", or an "interface".)
2. Using the "ref" keyword has NOTHING WHATSOEVER to do with boxing. It merely passes the address to the variable, rather than the "value" of the variable. This means that any modification to the variable within the called method will change the variable in the calling method.
3. When passed by "ref", the address ALWAYS points to an object on the STACK. This is how we know that the referenced item can't move. It's on the stack underneath the current method call.
This thread really isn't about the mechanics of the CLR though. If you don't understand them, then please ask a question in another thread.
-ps. Serapth- I said all of the "XNA Authors" are probably former C++. Ask them. Pretty much all Microsoft C# programmers are former C++ coders. About 95%+. Jurak wrote:
This thread really isn't about the mechanics of the CLR though. If you don't understand them, then please ask a question in another thread.Well, it is really, as it's the mechanics that dictate the performance you mention
.I'll always be able to rewrite the XNA matrix to be more efficient - for instance think about how you can optimise the maths (and storage) if you know the transformation matrix is always affine. But I guess the optimisation you mention is a no-brainer really (apart from the fact that I know of no case where an exact equality check is useful for comparing matrices
).Anyhow, you're right, the MSIL doesn't box the struct- I just had a typo in my test case. (It is 2.00am here!)
Andy.
Edit: And of course, now is the time to sort the perf out.
- You are right that Matrix comparison is rarely needed, but I do have a part of my rendering engine that checks to make sure a state change is needed before applying it. That requires checking matrices.
Can you say it's not useful to call Vector3.Transform(Vector3 v, Matrix m)?
If you have 1000 vertexes to transform (and there are very good reasons to do this from outside of a vertex shader), then is it a good idea to pass a matrix by value, a vector by value, then reassign the vector by value for every single one? I don't think so.
What's wrong with adding
///<Summary>
/// Transforms the vector v by the matrix m and leaves the result in v.
// Matrix m is not modified by this call.
///</Summary>
public static void Vector3.Transform(ref Vector3 v, ref Matrix m);
This doesn't make anything harder for the novice developers since they can still use the easily understandable "by value" method, but provides the performance that some of us need for our engines.
As it is I will have to write yet another Matrix Vector transform function (for the millionth time). And that is a real disappointment.
edit- if I don't do the matrix comparisons to reduce redundant API calls, then I run about 7fps slower than normal. Jurak wrote:
What's wrong with adding
///<Summary>
/// Transforms the vector v by the matrix m and leaves the result in v.
// Matrix m is not modified by this call.
///</Summary>
public static void Vector3.Transform(ref Vector3 v, ref Matrix m);
This doesn't make anything harder for the novice developers since they can still use the easily understandable "by value" method, but provides the performance that some of us need for our engines.
As it is I will have to write yet another Matrix Vector transform function (for the millionth time). And that is a real disappointment.Hey, I'm not arguing
.I guess I have such low expectations of any 3rd party maths library that I expect to have to write my own, as they are always missing something I need, and invariably slower than optimal. What worries me is that any future VMX optimisations might be applied to the XNA maths classes only, so if we use our own structs/classes we will be screwed!
Edit: And I wouldn't advocate leaving in the non-ref versions for the same reason I'd shoot anyone passing matrices on the stack in C++. Why teach bad habits?
Jurak wrote: Serapth- Your understanding of "boxing", "structs", "references" and "values" within the .Net CLR framework is incorrect.
1. Boxing only occurs when a struct is assigned to a "reference" type variable. (such as "object", or an "interface".)
2. Using the "ref" keyword has NOTHING WHATSOEVER to do with boxing. It merely passes the address to the variable, rather than the "value" of the variable. This means that any modification to the variable within the called method will change the variable in the calling method.
3. When passed by "ref", the address ALWAYS points to an object on the STACK. This is how we know that the referenced item can't move. It's on the stack underneath the current method call.
This thread really isn't about the mechanics of the CLR though. If you don't understand them, then please ask a question in another thread.
-ps. Serapth- I said all of the "XNA Authors" are probably former C++. Ask them. Pretty much all Microsoft C# programmers are former C++ coders. About 95%+.I by no means pretend to be an expert on managed code, like I said earlier I have come from a C++ background and have mostly used C# in areas where performance really didnt mean a damned thing. However, everything I have read ( unless, like I said, in the last few C# revisions has changed ) says you are wrong on a few points here. Please don't take this as hostility, it isnt.
1. Boxing only occurs when a struct is assigned to a "reference" type variable. (such as "object", or an "interface".)
This may be a simple miscommunication between us, Im not sure. A struct is a value type ( like an intrinsic int ), so if passed to a managed object or collection, it is boxed. I have a feeling we are saying the same thing. Keep in mind my origonal responce wasnt to you, it was in explanation of why he saw certain types being boxed. However, passing an intrinsic type or struct where a class derived from object is expected, will result in boxing.2. Using the "ref" keyword has NOTHING WHATSOEVER to do with boxing. It merely passes the address to the variable, rather than the "value" of the variable. This means that any modification to the variable within the called method will change the variable in the calling method.
"ref" itself has nothing to do with boxing, but if the function is something like void foo(ref Object myFoo) and you pass in a struct, it will be boxed and the resulting boxed value will be passed in. Atleast, this is how I understand it. So yes, "ref" itself has no end result but what is "ref'd" will have an impact.
For example from the language reference on boxing:
Since structs are not reference types, these operations are implemented differently for struct types. When a value of a struct type is converted to type object or to an interface type that is implemented by the struct, a boxing operation takes place. Likewise, when a value of type object or a value of an interface type is converted back to a struct type, an unboxing operation takes place. A key difference from the same operations on class types is that boxing and unboxing copies the struct value either into or out of the boxed instance. Thus, following a boxing or unboxing operation, changes made to the unboxed struct are not reflected in the boxed struct.
All I was saying is, there are cases, even when ref is used, where items get boxed.
As to your 3rd point, I admit, I mangled termenongly about stack and heap to the point, I wont even bother arguing! :)
As to the XNA authors bit, im still not sure. I have talked to many people with only introductory programming experience that are excited by XNA. Also, Microsoft in their own literature talked about XNA reaching the masses. I will agree thought that the vast majority of C# programmers have a C++ background *in the professional world*. I think thats my distinction. I think there are a ton of people interested in XNA that have never written a line of C++ code.
- The .NET Framework Design Guidelines Book has a section on choosing struct (value type) over class (reference type).
They recommend you do NOT use struct if your type is over 16 bytes or immutable (amoung other things).
This Matrix type at 64 bytes is well over 16 bytes AND is not immutable.
It would be interesting to know why the XNA team decided to ignore both recommendations from the team behind the CLR/Framework.
[)amien Serapth,
Read above - I've checked the MSIL and there is no boxing (only my typos!)
As for XNA being for hobby developers - XNA set out to make professional games development faster and cheaper. It just so happens that the XNA framework (a small part of XNA) has been released to the hobby market first, before the pro version is completed.
DamienG wrote:
It would be interesting to know why the XNA team decided to ignore both recommendations from the team behind the CLR/Framework.Can't speak for them in person, but I suspect it is to speed up marshalling into native code.
AndyL wrote: Serapth,
Read above - I've checked the MSIL and there is no boxing (only my typos!)
As for XNA being for hobby developers - XNA set out to make professional games development faster and cheaper. It just so happens that the XNA framework (a small part of XNA) has been released to the hobby market first, before the pro version is completed.
Dont get me wrong, im not saying XNA is *Only* for hobby devs, im saying many people out there are hobby devs. Keep in mind, there are two versions of XNA, the version we have now ( hobby oriented ) and a version to be released in the near future, which is the pro version. Im not saying XNA isnt capable of creating professional games. Im just saying what we have no is mostly targeted at smaller dev houses and hobby programmers. This is probrably why we cant use Visual Studio professional yet :(
I have nothing against XNA, and I especially have nothing against C#. Don't read my words that way.
As to the fact your MSIL turned out to be mistaken, there are cases where a ref value would be passed as a boxed type, that was all I was trying to explain. Alot of this thread has just been a giant miscommunication.
- Those .Net guidelines are very well known, and are... well "guidelines". Tom Miller's choice of struct for type Matrix was and is the correct choice. The "guidelines" also strongly advice against directly exposing public fields. But wrapping getters and setters around what is purely structural data like vector and matrix fields would be worse than pointless.
The .Net guidelines are well suited for development of public API's within the System.* namespaces, and are good guidelines for general development. But Graphics API's are a place where performance has a very high priority, which is why you will see deviations like using larger than normal structs, and exposing public fields. Those choices are perfectly appropriate for this API.
Matrix is perfectly fine being a struct. It's just not smart to pass it around by value. - Serapth-
Your assertion that using the "ref" keyword can result in boxing is completely wrong. (still)
Try compiling your "void foo(ref Object myFoo)" and see what happens when you try to pass any value type by ref to it.
If you really want to understand what causes boxing, and what doesn't, compile your code samples and experiments, run ILDASM, and look for the "box" il instruction.
- You still didn't understant what I said about the "XNA Developers". I did not mean the vast unwashed XNA "users". I'm talking about the developers who work at microsoft that wrote XNA. Those are the ones that are probably exclusively EX-C++ developers. As for the "users" I am sure it is a mix of C++/Java/VB etc. Serapth,
the age old addage - RTFM. I've just done that, as I wasn't clear on this issue, and so:
12.4.1.5.2 By-ref parameters
By-ref parameters are the equivalent of C++ reference parameters or PASCAL
var parameters: instead ofpassing as an argument the value of a variable, field, or array element, its address is passed instead; and any
assignment to the corresponding parameter actually modifies the corresponding caller’s variable, field, or array
element. Much of this work is done by the higher-level language, which hides from the user the need to
compute addresses to pass a value and the use of indirection to reference or update values.
Taken from the CLR ECMA spec.
So there you are, 'ref Matrix m' really does work like 'Matrix& m' or 'Matrix* m' does in C++, no boxing or any other £%*!#~. Lovely.
Andy.
- Looks to me like all of the Matrix and Vector methods could do with having ref added.
Well I'll second rewriting the Vector and Matrix classes to use ref - presumably where applicable they should also return structs using 'out'?
Jurak - Have you filed a bug report for this?
Andy.
- Yes, it's in "Bugs" with the title "Matrix operations performance is broken."
I could've filed under suggestions, but I consider it a bug that an end user can write faster standard math routines. Jurak wrote: Yes, it's in "Bugs" with the title "Matrix operations performance is broken."
I could've filed under suggestions, but I consider it a bug that an end user can write faster standard math routines.
Disclaimer: I have no opinion on whether you are right or wrong with your assertions in this thread.
I want to see data. I'm tired of people posting in these forums handwaving about performance with no numbers and more importantly, NO CODE to back it up. Why don't you write up a quick app that shows us just how poor it is, contrasting the Equals() you wrote with the one that comes with XNA as well as the Vector multiplication.- Dodger- the performance difference is based upon passing 2 matrices by value or by reference. Copying 8 bytes will always be faster than copying 128 bytes. It's that simple. You don't need tests to know that. But here are the results and code anyways:
// Matrix.Equals is about 10 times more performant when the matrices are different.
\Active\Test\bin\Release>Test.exe
TestMatrix == 0.789511209578517
TestMatrix Equals 0.0887999198003028// Matrix.Equals is about 5 times more performant when the matrices are identical.
\Active\Test\bin\Release>Test.exe
TestMatrix == 1.14198027622112
TestMatrix Equals 0.23817280896098
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using System.Runtime.InteropServices;
using System.Security;
namespace Test
{
public class Native
{
[SuppressUnmanagedCodeSecurity]
[DllImport("Kernel32.dll")]
static extern bool QueryPerformanceCounter(out long count);
[SuppressUnmanagedCodeSecurity]
[DllImport("Kernel32.dll")]
static extern bool QueryPerformanceFrequency(out long frequency);
static long frequency = 0;
static long start = 0;
/// <summary>
/// Returns the total elapsed time in seconds relative to the first time it is called.
/// </summary>
public static double Time
{
get
{
if (start == 0)
{
QueryPerformanceFrequency(out frequency);
QueryPerformanceCounter(out start);
return 0;
}
long time;
QueryPerformanceCounter(out time);
return (time - start) / (double)frequency;
}
}
}
class Program
{
static Matrix[] matrices = CreateMatrixArray(1000, false);
static Matrix[] CreateMatrixArray(int size, bool randomValues)
{
Random random = new Random();
Matrix[] matrices = new Matrix[size];
for (int i = 0; i < matrices.Length; i++)
{
Matrix matrix = Matrix.Identity;
if (randomValues)
matrix = Matrix.CreatePerspectiveFieldOfView((float)random.NextDouble() + 0.5f, (float)random.NextDouble() + 0.2f, (float)random.NextDouble() - 1f, (float)random.NextDouble() + 1f);
matrices
= matrix;
}
return matrices;
}
public static void Main()
{
TestMatrixEquals1(10000);
TestMatrixEquals2(10000);
}
public static void TestMatrixEquals1(int count)
{
double start = Native.Time;
int matches = 0;
for (int i = 0; i < count; i++)
{
for (int k = 1; k < matrices.Length; k++)
{
if (matrices[k - 1] == matrices[k])
matches++;
}
}
double finish = Native.Time;
double time = finish - start;
Console.WriteLine("TestMatrix == " + time + " " + matches);
}
public static void TestMatrixEquals2(int count)
{
double start = Native.Time;
int matches = 0;
for (int i = 0; i < count; i++)
{
for (int k = 1; k < matrices.Length; k++)
{
if (Equals(ref matrices[k-1], ref matrices[k]))
matches++;
}
}
double finish = Native.Time;
double time = finish - start;
Console.WriteLine("TestMatrix Equals " + time + " " + matches);
}
public static bool Equals(ref Matrix a, ref Matrix b)
{
// i check the diagonal first for quick fails
return a.M11 == b.M11
&& a.M22 == b.M22
&& a.M33 == b.M33
&& a.M44 == b.M44
&& a.M12 == b.M12
&& a.M13 == b.M13
&& a.M14 == b.M14
&& a.M21 == b.M21
&& a.M23 == b.M23
&& a.M24 == b.M24
&& a.M31 == b.M31
&& a.M32 == b.M32
&& a.M34 == b.M34
&& a.M41 == b.M41
&& a.M42 == b.M42
&& a.M43 == b.M43;
}
}
}
What's wrong with adding
///<Summary>
/// Transforms the vector v by the matrix m and leaves the result in v.
// Matrix m is not modified by this call.
///</Summary>
public static void Vector3.Transform(ref Vector3 v, ref Matrix m);
My only concern is that it is done in a language neutral fashion. There are several of these type overloads in DirectX and it causes huge problems in VB. I haven't checked to see if this problem has been addressed in 2005. In VB this used to keep you from using either overload, because it can't tell the different between these two methods:public static void Vector3.Transform(Vector3 v, Matrix m);
public static void Vector3.Transform(ref Vector3 v, ref Matrix m);Of course, I'm not saying the framework should be crippled because of VB, but they totally screwed me in DirectX because of this, so it'd be nice to implement it in a way that works for everyone.
I think another solution would be a compiler option that says something to the effect of 'Pass all value types by ref' and this would be applied to all code for the application, and possibly all linked assemblies as well (don't know if that's possible). The danger would be that code would behave incorrectly if it modified these value parameters that it assumed were copies of the original value type, so something would need to be devised to solve that...
If that's not possible I agree that ref overloads for all the major math and graphics functions would be nice.
Maybe the implementors of matrix and vector and other value types could just do a memory compare for equality?

Check out this post by Rico Mariani on this very topic:
- The compiler option has already been suggested and rejected in the feedback. It's probably beyond the scope of what the developers can likely do. (They definitely have no control over it on the windows runtime.)
Passing with "ref" is a perfectly acceptable standard language feature, and should be utilized where appropriate.
Some feedback from the developers on when/if they have any intention of providing this would be nice. - Joel-
No, that is not the same topic. That is discussing why Matrix and Vector are value types (structs ) vs reference types (classes).
I have no problem with them being structs. They are perfect as structs, and in no way do I want them to be something else.
I just want them to use the "ref" keyword where appropriate when passing them (Matrix especially) because copying them by value onto the stack to pass to a method is SO expensive.
Please read AndyL's earlier post from the ecma spec that explains the "ref" keyword. It has nothing to do with the reference type vs value type issue. Serapth wrote: {...} I don't think this is yet the time to worry about performance. The age old axiom of make it work then make it fast is a good thing. I hope by final release they add optimized options but right now I don't think it should be the focus. This is doubly true given XNAs focus on Indy and beginning developers, which actually adds a 3rd aspect to that equation. Make it work, make it easy, then make it fast.
{Emphasis mine...}
I hate to interrupt the "boxing match", but I REALLY hope someone from MS is still reading this...
If your target is beginning developers then it's even MORE important that you optimize your end of the deal right off the bat. I read all of these articles dealing with quadtree collision detection and all sorts of other tricks to get big-O to the floor... when you know good and well us beginners are going to use the obvious but inefficient brute-force methods. And when our pathetic Geometry Wars clone grinds to a halt we're going to assume that either a) we suck, or b) XNA sucks... either way, there's a good chance we'll have given up before your "pro" optimized version comes out.
noob who still can't believe the TI-99/4a was the last environment he saw built-in sprites (I really thought XNA would change that.. sigh),
MattSerapth wrote: {...} I don't think this is yet the time to worry about performance. The age old axiom of make it work then make it fast is a good thing. I hope by final release they add optimized options but right now I don't think it should be the focus. This is doubly true given XNAs focus on Indy and beginning developers, which actually adds a 3rd aspect to that equation. Make it work, make it easy, then make it fast.
{Emphasis mine...}
I hate to interrupt the "boxing match", but I REALLY hope someone from MS is still reading this...
If your target is beginning developers then it's even MORE important that you optimize your end of the deal right off the bat. I read all of these articles dealing with quadtree collision detection and all sorts of other tricks to get big-O to the floor... when you know good and well us beginners are going to use the obvious but inefficient brute-force methods. And when our pathetic Geometry Wars clone grinds to a halt we're going to assume that either a) we suck, or b) XNA sucks... either way, there's a good chance we'll have given up before your "pro" optimized version comes out.
noob who still can't believe the TI-99/4a was the last environment he saw built-in sprites (I really thought XNA would change that.. sigh),
Matt- I have created a ray tracing engine in C#. During this, I created my own geometry library, as you do. It is my experience that almost 100% of the time, passing a struct by ref is faster, if the structure size is more than about 13 bytes. I think that for every structure that is larger than 12 bytes, the maths methods should include a ref variant, with no exception.
I've been reading the this and it got boring real quick. As you guy got involved in the politics and symantic.
So I wrote at little apps to test which was quickest. By crunching the by value and the by ref head to head.
Well that all I care is speed as the complex are inconsequencial. As any one developing wheather a pro or a hobbist like me want to eventually to publish.
This means we will take the effort to learn how to do it the quickest way no matter what. As every won measures frames per second!
The verdict is by Ref was between 5 and 18 times faster depending on things.
End of story....
I've been working with MDX for about 2 years. My friend makes a new set of math classes and it was 5 times faster that the MDX built-in.
If you do not think that for a GAME framework we need speed, you do not know about writing games. The Matrix struct and the vector struct problem is well known, and i think it's a must, to make it by ref, and not by value. Think on skinning, please, when you have a lot of matrix multiply every frame...The name of the post is clear: if you do not make the ref option a reality, WE must write a new set of math classes.
- I'm going to have to agree, it would be nice to have some "ref" overloads. While working on a 2D physics engine for XNA, I've found that even the built in Vector2 methods are not as quick as passing by ref and doing the math myself. It's not a big difference per single call, but they add up when doing collision detection/response...
- Sounds like I'm not the only one sick of writing and re-writing my own math functions.
We are just asking that you make the Math library in XNA as fast it CAN BE.
The truth is, that it CAN BE just as fast as the Direct3D C++ math library IF you will pass structures by reference just like they do.
Why do they pass structures by reference in C++?
Because it's faster.
Why wouldn't you do that in C#?
Xna developers: Can we please have a Math API in XNA that is optimized? Jeff Weber wrote: I'm going to have to agree, it would be nice to have some "ref" overloads. While working on a 2D physics engine for XNA, I've found that even the built in Vector2 methods are not as quick as passing by ref and doing the math myself. It's not a big difference per single call, but they add up when doing collision detection/response... You're working on a 2d physics engine? Have anything to show so far? I want to do some 2d games, but don't want to reinvent the wheel.
Hopefully in a few weeks some good xna game components will start to appear. Ideally MS could host them, and allow ratings & comments so 'best of breed' can bubble up to the top.
I've requested project space on CodePlex. Once they get that set up I will put what I've currently got out there. It's got all you basic Rigid Body stuff: forces, torques, polygon collision detection/response, friction, drag.. etc. No joints yet but they are in the future plans. One thing on my list is to optimize it. I've run some stress tests and it is not performing as fast as I would like. I am currently relying on the XNA math constructs (vector,matrix) and corresponding methods they expose, which is why I'd like them to be a little quicker.
Btw, the engine will be called "Farseer Physics Engine" on CodePlex so keep an eye out.
- I wonder why none of the MSFT guys have addressed this post at this point. It seems like a fairly significant issue.
- Have we all verified there is a feedback item for this that has lots of people voting on it?
- I have a feedback issue open titled " Matrix operations performance is broken". 4 votes so far, all 5.0 priority. Please add to this.
DaveSmith wrote: I wonder why none of the MSFT guys have addressed this post at this point. It seems like a fairly significant issue. I wonder what their opinion is too, so here goes a shameless bump
.Andy.
- Shawn Hargreaves gave a generic answer that said they were at least aware of it.
I can only imagine that some developers on the team are aware of the performance problems since they've existed since MDX1.0.
That leads me to assume that someone with architectural control over the API is against using the 'ref' keyword for some less than practical reason.
It would really be nice to see some honest discussion on these forums between the Api users and developers about this. - This is also HUGE for sprite drawing, since the SpriteBatch class uses Matrix internally. Even if we write our own math library, we have no control over the inner XNA library which will still be passing Matrix, Vector, Rectangle, etc. all over the place by value.
- It's a big issue as I was hoping that the XNA meant and end to the days of having to set up lots of functionality that is totally generic to videogames, before starting work on a simple application.
Although mentioned that there isn't any way to change the behavior of Matrix/Vertex inside the library, the new C# 3.0 extension methods could help here in application code by allowing you to add your math code right in to the classes. Instead of having MathUtils.MatrixMultiply(...) you could just have an overload for Matrix.Multiply that took the matrices by reference.
Of course C# 3.0 probably won't be supported by XNA on the 360 (or at least not for awhile - it'd be cool if there was an eventual update), but for those developing for Windows it would work.- Did anything ever become of this?
- Yes. There are ref versions of most math functions.
- So the listened then. I don't think anyone can have any complaints really there.
Note that there are some cases (I think Equals is one of them) where we couldn't add ref versions of methods because it would prevent us from supporting other languages (Visual Basic, etc...) in the future because some languages cannot properly disambiguate ref and non-ref versions of methods.
Paul

