8

I'm currently reading Oreilly's Learning XNA 4.0 and I've noticed that the author is prone to creating a struct value, such as Vector2 or Rectangle multiple times with no regard for performance.

For example, a SquareCollision() method, that checks the collision between two game entities creates two Rectangles every time it is called, instead of simply having each game entity hold its own Rectangle field and compare the fields without creating any more struct values.

I've seen this pattern many times in many places and that made me wonder:
Is the creation of struct values that negligible in C#?
Does this really fall under the micro-optimizations section?

Perhaps because my experience is mostly with Java, the concept of ValueTypes is strange to me, but it seems that recreating a value from a struct (and calling it's constructor) multiple times seems like a giant waste of resources.

Acidic
  • 6,154
  • 12
  • 46
  • 80
  • I think this is a bit hard to profile, because what really matters is the overall performance hit. Even if recreating the same value is 10,000 times slower than using a field, it would still mean little if it's only a 0.0001% hit on performance. (Sorry for the arbitrary numbers, just trying make sure I'm understood.) What I'm trying to understand is how bad of a practice it really is (if at all) and whether or not I should try to avoid doing it. – Acidic Feb 12 '12 at 22:33
  • 1
    You could make the question a little more concrete by showing the code. Prevents misunderstandings. – H H Feb 12 '12 at 22:34
  • I have always wondered about the difference for example of `Point p; p.X=1; p.Y=2` vs. `p = new Point(1,2)`. Maybe for the compiler it makes no difference in the end. – John Alexiou Feb 12 '12 at 23:23

3 Answers3

8

Creating a struct for brief use on the stack is very cheap, and is not much different to just setting local variables for all those values, but with componentisation. However, as part of the object it would be an additional duplicate of the same data per object.

Both approaches are valid, depending on the scenario. On the stack, however, there is no real resource cost. As part of an object, you'd want to make sure you weren't duplicating data unnecessarily, as that would have actual cost.

If it were a property on an object, you'd need to copy it lots of times.

If it were a field on an object, yes: it could be used in-place without ever copying, but: this is relatively small in most cases.

As always, you'd need to profile to know if it mattered.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • It seems to me that the only way out of this is to use protected / public **fields** to make sure the same struct is used all the time, instead of it being duplicated unnecessarily. Or perhaps a method that receives structs by reference using the `ref` keyword? – Acidic Feb 12 '12 at 22:49
  • 1
    @Acidic if you use the struct **directly** (not assigning to a variable etc), then it doesn't need a copy; but yes - methods that take structs via "ref" are fairly common in this scenario. I use that approach myself in some crazy optimised places. – Marc Gravell Feb 12 '12 at 22:52
2

The thing that having that struct inside your (say) Mesh object will not benefit to you, basically. Cause at the moment of the request to it, the value of the struct will be copied. Consider example:

public class Mesh 
{
  public Vector3 MeshCogVector {get;set};
}

and somewhere in the code you have

public void CollisionDetection
{
    for(int i=0;....)
    {
       Mesh curmesh = listofmashes[i];
       Vector3 vec3 = curmesh.MeshCogVector; //value copied

    }
}

So using in this way in your conditions, you basically don't get any benefit + you increase your Mesh instance size.

Instead using/constructing that Vector3 instance inside actual method, in the moment you actually need it, you get fast on stack allocation and fast garbage collection.

If you don't satisfied with a performance in structures, can consider of using non safe arrays of data. But this is something that you should to measure, in order to understand if this is suitable scenario for you.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • wouldn't this be solved if I simply use a public field instead of a public property? As I understand it, struct properties create a new copy of the struct on the getter call. – Acidic Feb 12 '12 at 22:44
  • 1
    @Acidic: no, it wouldn't change anything. It's not about access way property/field/function return parameter, it's about the [C# value types](http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx). You may **try**, if you want to hold a `Vector` inside the class, to pass it with `ref` keyword the functions like `CollisionDetection`. In this case, the value will not be copied, but passed **by reference**. But it's something, again, that you have to measure. I would go, if the `Vector` class is not big, for the solution you already seen, so allocating in the moment when needed. – Tigran Feb 12 '12 at 22:52
  • I hate to ask such questions, but what is *big*? A `Vector2` might not be big, but what about `Vector4` or `Rectangle`? I guess *this* can only be answered with profiling... – Acidic Feb 12 '12 at 22:58
  • The good answer could be this one [Why 16 byte is recommended size](http://stackoverflow.com/questions/2407691/c-struct-design-why-16-byte-is-recommended-size). In this case `Vector` only with 3 floats `x`, `y`, `z` can be still "feasible" – Tigran Feb 12 '12 at 23:04
  • @Acidic: Properties of struct type operate by returning an entire struct, even if the code reading the struct simply reads a field. Public fields of struct type don't have that problem. Note that some ancient C# compilers would allow one to write to the fields of a returned struct property (which, since the return value of the property was just a temp, would have no effect). At the time, the best way to prevent that problem was for structs to disallow any means of writing to fields except in the constructor. Given that modern compilers no longer allow silly writes to temps, ... – supercat Feb 16 '12 at 03:39
  • @Acidic: ...structs should, when practical, expose their state as mutable fields. Note that any non-trivial struct which is stored in a mutable storage location is mutable, *regardless of whether it exposes any means of modification outside its constructor*. Conversely, any struct stored in a non-writable storage location will be immutable, even if it exposes public fields. Mutable structs have semantics which differ from class types in useful ways, provided they are exposed as fields rather than properties. – supercat Feb 16 '12 at 03:47
0

All the attributes present in the struct are present in memory as contiguous memory allocation which means all attributes are present side by side so accessing each attributes , structs makes it simple for CPU . Where as Following core OPP concepts can decrease the performance e.g. In class if you have var Power and from the other script if you are referencing this value then CPU reference all the locations of Attributes present in that class (As all data is present on Heap at random location so more work for CPU to Do) called as line caching .

Solution

[System.Serializeable]
public Struct SomeclassData(){  

Vector3 vec;
float value;
// some numeric data or vector data  }


public class SomeClass : Monobehaviour{
SomeclassData data;

void Start(){
 data = new SomeClassData();
}

}
DevHawk
  • 23
  • 8