Kylo Ren
Kylo Ren

Reputation: 8813

c# struct vs Class performace, Design focus

How much performance gain could be achieved using struct over class? Should I design the apps focusing the maximize use of struct over class?

Can I convert my classes into struct and move functions into another static classes wherever it's possible?

Upvotes: 8

Views: 7998

Answers (5)

Anders Forsgren
Anders Forsgren

Reputation: 11101

The msdn recommendations (listed in another answer) offers some guidance. For performance you should consider their usage and where the difference between structs and classes matter. The most important thing is to only use structs when the type is an actual value type, i.e. has value semantics. Using a class for a value type, or a struct for something that should be a reference type will quickly give confusing results with unintened copying or unintended references. Also remember that structs should always be immutable.

Only in extremely performance-sensitive situations should you ignore any of these basic rules (Case in point: The framework breaks the rules for the List.Enumerator structure!).

Perf considerations for structs vs classes:

If you pass your struct as an argument to a method, you will create a copy of the struct each time. This is why the docs recommend not making structs larger than 16 bytes.

double Distance(Vector3D a, Vector3D b)   // Copies both 24-byte structs
{
   return Math.Sqrt((a.X - b.X *....);
}

In the scenario above, a 3D vector of 3 doubles would make 24 bytes and would be larger than the recommended 16, but I'd still argue that a struct makes sense since it is clearly a value type, especially you have a Vector2D containing two doubles (16 bytes) that is a struct!

The key to using structs efficiently, and where their performance really shines, is to use them for cache locality and avoiding many allocations. To re-use the Vector example above, if you have this method

double AverageDistanceFromOrigin(Vector3D[] points) // Single reference passed
{
   double sum = 0.0;
   for(...)                                         
      sum += Math.Sqrt(points[i].X... + ... + ...)  // No copies
   return sum/points.Length;
}

You may see a good performance difference in favor of structs. The reason is that now you are passing a single reference (the array) to the method, so there is no extra overhead for copying the struct per call(Note that the method does not call a distance-method for each entry in the array).

The array-of-structs is also laid out consecutively in memory like [x1, y1, z1, x2, y2, ...] so the cpu will load e.g. 16 coordinates at a time into the cache , leading to few cache misses. Compare that to a class Vector3D implementation: now an array of vectors will be allocated and each entry in the array will also be a reference that has to be heap allocated, and later garbage collected. The array is now an array of references [ref to v1, ref to v2, ref to v3] each of which may have any address in the heap, and may not sit next to eachother. This can lead to many more cache misses than the struct case.

  • Use structs only if your type has value semantics (and vice versa).
  • Don't pass large structs individually to methods; Operate on lists/arrays of structs to avoid copying
  • Don't consider the 16-byte limit as a hard limit: you can use much larger structs, but remember to avoid passing them individually to methods.

Upvotes: 14

spaceman
spaceman

Reputation: 1101

Converting your structs to classes will not automatically improve the performance of your application.
It depends on how you use them, vs how you used your class objects.

If you create and destroy alot of objects of a class, you can either reuse an object of that class, or create a struct and reuse it too
(so you see, you could do that with a class too).

When you call a method and send parameters or return a value,
a class is passed by reference, and a struct is passed by value.
So here you might enjoy performance gain, if you pass it alot of time.
(yet again, with good programming you can even avoid passing it all the time to the method, by making the data as a field(s) of the class that contains the methods).

Regarding your second question,
you can have methods inside a struct too, you don't necessarily need to move them to a static class.

struct SimpleStruct
{
    private int xval;

    public int X
    {
        get 
        {
            return xval;
        }
        set 
        {
            if (value < 100)    xval = value;
        }
    }

    public void DisplayX()
    {
        Console.WriteLine("The stored value is: "+xval);
    }
}

https://msdn.microsoft.com/en-us/library/aa288471.aspx

Upvotes: 0

Jon Hanna
Jon Hanna

Reputation: 113242

How much performance gain could be achieved using struct over class?

For "could be" the answer would be that you could many times faster.

However it could also be many times slower.

Most of the time it'll be neither, but just give a slight gain or loss.

So "I'll use structs to be faster" is, on its own, wrong-headed thinking.

If your starting point is to consider whether something should be a ValueType because it should indeed be a value-type; defined, used and reasoned-about solely in terms of its value, or should not be a ValueType because it is not such a value-type, then you're likely going to have the most performant choice for that particular case a good 95% or more of the time.

Of the remaining 5%, probably 90% of those will only be negligibly less performant if you'd gone the other way, and/or they just won't be in hot enough paths for it to matter. (Say you save 20 milliseconds on a given method. If that method is called a million times then you've saved five and a half hours of run time, but if it's called once you've saved 20 milliseconds you won't even notice).

Of the cases where we would actually want to change between value and reference types for performance reasons, we might very often go from struct to class rather than the other way around. Indeed so much so that avoiding value types being much over 16 bytes in size is an oft-cited guideline though really that's a performance optimisation rather than an inherent part of what it means to be a value or reference type.

It's also worth noting the differences in value and reference types by calling code. There are some operations that can be much quicker on arrays of mutable structs than on arrays (or any other collection) of mutable reference types. But taking advantage of those requires that you both make the fields public and the value-types mutable; both things that can cause considerable difficulties. Such optimisations are reasonable for private types within a class that uses them, and at a push for internal types, but if done with public types it's asking for trouble.

Upvotes: 1

Rahul Tripathi
Rahul Tripathi

Reputation: 172428

The MSDN has good points to that:

✓ CONSIDER defining a struct instead of a class if instances of the type are small and commonly short-lived or are commonly embedded in other objects.

X AVOID defining a struct unless the type has all of the following characteristics:

  1. It logically represents a single value, similar to primitive types (int, double, etc.).
  2. It has an instance size under 16 bytes.
  3. It is immutable.
  4. It will not have to be boxed frequently.

Also the MSDN has Struct Design

Should I design the apps focusing the maximize use of struct over class?

It depends on to what you are trying to implement. Structs are used when you have a small structures which you are trying to implement which will behave like values. So saying that using struct over class is not a ideal statement or approach.

Upvotes: 11

Leonardo Spina
Leonardo Spina

Reputation: 680

Well the short answer is "You can, but you shouldn't".

The main difference between classes and structures is that a structure defines a Value type, while a class defines a reference type. Therefore you can't actually just replace the "class" word with "struct" and move the functions, because the behavior of your program could be heavily affected by the above mentioned difference. Then, if you are designing a new application from scratch yes you can consider whether to define your logical objects using structures or classes where it is appropriate, but then your code has to keep that in mind. I hope this helps!

Upvotes: 3

Related Questions