C# vs C/C++: do I need to order struct fields manually for best performance?

224 Views Asked by At

I have just read this article on instruction and memory CPU cache awareness:

http://www.research.scea.com/research/pdfs/GDC2003_Memory_Optimization_18Mar03.pdf

The article reasoning is around using C/C++.

I have three related questions:

  1. Will C# generally follow same rules?

  2. Do I need to order struct fields manually for the best performance? Will compiler take care of this or it's not possible due to higher level?

  3. If yes, then how does this affect generic structures? E.g. struct Triple < T1, T2, T3 > { /.../ }

2

There are 2 best solutions below

2
On BEST ANSWER

Will C# generally follow same rules?

C# has the same issues as C and C++ in the sense that an unaligned structure can cause performance to suffer in certain (probably most) architectures.

Do I need to order struct fields manually for the best performance? Will compiler take care of this or it's not possible due to higher level?

Although it's probably allowed to, in practice the Microsoft compiler does not take care of this by default. [StructLayout(LayoutKind.Auto)] (which is the default) for structs is typically the same as [StructLayout(LayoutKind.Sequential)]. In C, struct members are required to be sequential and in C# they followed this choice as well.

With that out of the way, of course, compilers attempt to align struct members, because they optimize for performance but not for space. You may have figured out in your particular scenario that optimizing for space does improve performance, but this is too complicated for a compiler to deduce.

If yes, then how does this affect generic structures? E.g. struct Triple < T1, T2, T3 > { /.../ }

When you see a definition for a Triple<T1, T2, T3>, what you see in your code is what is called (in MSDN) a generic type definition. Every time you instantiate a new combination of the type parameters of this generic definition, a new runtime type is created by the environment (you may see it called something like Triple'1). That generated type isn't different from a non-generic type anymore and I see no reason why the JIT-compiler would treat it differently (but I could be wrong, of course).

2
On

By default, .NET is free to order class members however it wants. I assume it will pick an optimal layout, but I'm not certain of that. Struct layout by default will have the same layout semantics you're used to in C++. These are properties of the CLR and not C#.

You can control unmanaged layout explicitly with the StructLayout attribute:

using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct TestUnion 
{
    [FieldOffset(0)] 
    public int i;
    [FieldOffset(0)] 
    public double d;
    [FieldOffset(0)] 
    public char c;
    [FieldOffset(0)] 
    public byte b1;
}

General advice, of course, is to layout your code in whatever way is easiest for you to maintain.