Poor memory management can hurt performance in many ways. One such effect is called GC Pressure. This article will show 8 techniques to minimize GC pressure, and by doing so, improve performance.
tl;dr structs have better data locality. Value types add much less pressure for the GC than reference types. But big value types are expensive to copy and you can accidentally box them which is bad. Introduction The .NET framework implements Reference Types and Value Types. C# allows us to define custom value types by using struct and enum keywords. class, delegate and interface are for reference types. Primitive types, like byte, char, short, int and long are value types, but developers can’t define custom primitive types. In Java primitive types are also value types, but Java does not expose a possibility to define custom value types for developers ;) Value Types and Reference Types are very different in terms of performance characteristics. In my next blog posts, I am going to describe ref returns and locals, ValueTask<T> and Span<T>. But I need to clarify this matter first, so the readers can understand the benefits. Note: To keep my comparison simple I am going to use ValueTuple<int, int> and Tuple<int, int> as the examples. Memory Layout Every instance of a reference type has extra two fields that are used internally by CLR. ObjectHeader is a bitmask, which is used by CLR to store some additional information. For example: if you take a lock on a given object instance, this information is stored in ObjectHeader. MethodTable is a pointer to the Method Table, which is a set of metadata about given type. If you call a virtual method, then CLR jumps to the Method Table and obtains the address of the actual implementation and performs the actual call. Both hidden fields size is equal to the size of a pointer. So for 32 bit architecture, we have 8 bytes overhead and for 64 bit 16 bytes. Value Types don’t have any additional overhead members. What you see is what you get. This is why they are more limited in terms of features. You cannot derive from struct, lock it or write finalizer for it. RAM is very cheap. So, what’s all the fuss about?
Poor memory management can hurt performance in many ways. One such effect is called GC Pressure. This article will show 8 techniques to minimize GC pressure, and by doing so, improve performance.
I’m a massive fan of everything Fabien Sanglard does, I love his blog and I’ve read both his books cover-to-cover (for more info on his books, check out the recent Hansleminutes podcast).
It all started with a tweet, which seemed to resonate with people: