MSMVPS.COM
The Ultimate Destination for Blogs by Current and Former Microsoft Most Valuable Professionals.

The Big Performance Danger of Value Types (Structs)

I talk to many folks who are eager to use structs because of the great performance advantages. While it is true that a struct is much quicker to allocate than a reference type (class) (somewhere around an order of magnitude quicker if all the member variables are also value types), structs can have some very serious performance problems. These include:

  • When passed as a parameter, the memory of a value type need to be copied onto the stack, and if a very large value type is created, the cost of this copying can be significant. Value types should ideally by around ~20 bytes in size, with ~100 bytes being a general ceiling.
  • A call stack is only so big, and if you have very big value types passed as parameters, you'll end up with a stack overflow exception.
  • The big gotcha of value types is their equality and hashcode implementations. If a value type only contains other value types, all is sweet, as a bitwise equality check and simple hashcode calculations can be used. If a value type contains reference types, things get ugly. If two value types have member variables that are reference types, and these fields have different values (i.e. the pointer that points to the reference type is different), it is possible that these reference types will have overridden their equality operator to define equality in terms of member variable sameness (System.String is the prime example of this). Therefore, value types that have reference type member variables can be Equal (because all their member variables are Equal) even if they have different bits. To accommodate this scenario, a value type that has reference type member variables needs to use reflection (which is massively slower than bitwise equality) to do the equality checks on each member variable. Because objects that are Equal must have the same hashcode, GetHashCode has the same performance problems as Equals for value types with reference types.

    The end result of this is that you should always override Equals and GetHashCode on publicly visible value types if you have reference type member variable. FxCop goes further, and uses a dumbed-down (but justifiably cautious) explanation that states reflection is always used for value type equality without an explicit override. FxCop is a great tool for picking up these performance issues, and keeping an eye on its output is a good idea during the course of a development cycle.
    Posted Jul 28 2006, 02:53 AM by nick
    Filed under:
  • Comments

    David M. Kean wrote re: The Big Performance Danger of Value Types (Structs)
    on 07-27-2006 22:57
    Nick,

    You're right about the FxCop documentation; it is wrong in stipulating that ValueType.Equals always uses Reflection, and I will file a bug on it tomorrow.

    You are also more likely to see more FxCop rules targetting value types in the future, particularly around their size (Design Guidelines state around 16 bytes), and their immutability.

    Regards

    David


    Nick Wienholt wrote re: The Big Performance Danger of Value Types (Structs)
    on 07-28-2006 0:55
    Hi David,

    Great stuff - thanks for listening.

    Nick


    Copyright © is the original authors. Blog site is an independent site not sponsored by Microsoft. The Yoda blog server and the Brianna SQL server would like to thank www.ownwebnow.com and www.exchangedefender.com. They wouldn't be here and broadcasting without the generosity of Vlad Mazek and his companies.

    Powered by Community Server (Commercial Edition), by Telligent Systems