Struct Layouts Performance Tip

Most developers aware of that Structs needed to be in smaller size (16byte or less) so they can run efficiently as possible. If you are interested in how the Struct size contributes to better performance, please refer to this question. This post is about another less popular tip that may contribute to improve the efficiency of Structs.

Just a bit of back ground on Struct Layouts:

The way you structure your code, for example the order you specify fields within a type, is not necessarily the same way the CLR organize those fields. For performance reasons, CLR can re-arrange those fields of a type any way it chooses. Using StructureLayoutAttribute attribute, you can explicitly tell CLR the way you want to organize your fields. If you don’t specify a StructureLayoutAttribute, the compiler selects the most appropriate layout it thinks best.

For Structs, C# compiler creates the LayoutType.Sequnetial by default. This means the fields should stay in the order defined by the programmer.

(Note: For Reference types C# compiler selects the LayoutType.Auto by default.)

Below is a C# Struct with no explicit layout and the corresponding generated IL.

Struct1

The Structs are commonly used when interoperating with unmanaged code. Therefore the fields must stay in the order that programmer define for this to work. But most user defined value types/Structs you create have nothing to do with interoperability with unmanaged code. Therefore if you specify the LayoutKind.Auto, the runtime automatically decide the appropriate layout.

Struct2

If you do a quick benchmark on both layouts you see the LayoutKind.Auto is much faster than the LayoutKind.Sequential.

Struct3

Result– (Time in milliseconds)

Struct4

(Config: .NET 4, x86, and Release build)

If you want to play around, you can download the sample code given below.





1 comment:

Anonymous said...

Your benchmark results make no sense. The layout generated for Auto and Sequential is the same in this case, and the optimized assembly generated by the JIT is also the same for both your test methods.

Your benchmark code leads itself to inaccuracies; you should always call the test methods once before testing them, to remove JIT compilation time from the equation; you should also alternate calls to the compared methods rather than do all of one first and all of the other after. With these corrections the test result is that they take strictly the same time.

StructLayout.Auto may result in a size optimization in some cases but is generally pointless. It does *not* provide significant performance benefits.