views:

990

answers:

6

When you need to have very small objects, say that contains 2 float property, and you will have millions of them that aren't gonna be "destroyed" right away, are structs a better choice or classes?

Like in xna as a library, there are point3s, etc as structs but if you need to hold onto those values for a long time, would it pose a performance threat?

+1  A: 

The big concern is whether the memory is allocated on the stack or the heap. Structs go in the stack by default, and the stack is generally much more limited in terms of space. So creating a whole bunch of structs just like that can be a problem.

In practice, though, I don't really think it's that big of a deal. If you have that many of them they're likely part of a class instance (on the heap) somewhere.

Joel Coehoorn
The stack space is not a concern for structs, as you rarely have that many local variables. If you create an array of structs it will be allocated on the heap, not the stack.
Guffa
I think that was my point: if you _do_ have that many it's a problem, but you're not likely to have that many.
Joel Coehoorn
If you do have that many variables it's a problem regardless if it's a struct or a class, as the references would also be allocated on the stack... :)
Guffa
Thanks Joel. So if have a list of 1M point3 struct values, they are gonna be stored on the heap?
Joan Venge
Yes, they will.
Joel Coehoorn
+1  A: 

Value types (struct) are good for type that are not allocated on heap often, that is, they are mostly contained in another reference or value type.

The Vector3 example you gave is a perfect example. You will rarely have dangling Vector3 in heap, they will most of the time be contained in a type that is itself in heap, or used as a local variable, in which case, it will be allocated on the stack.

Coincoin
Thanks, so structs will be on the heap only if used as a local variable, and nothing else?
Joan Venge
No, it's the other way around. A value type like a struct is only allocated on the stack if it's a local variable. If it's a member of a class, it's allocated as part of the object's memory area on the heap.
Guffa
+1  A: 

Struct seems right for this application.

Bear in mind that the "need to hold onto those valueS" implies their storage on the heap somewhere, probably an array field of a class instance.

One thing to watch out for is that this results in a allocation on the large object heap. Its not that clear how, if at all, this heap defrags itself, however for very long lived objects that perhaps isn't an issue.

Using class for millions of these data types would likely be expensive in the shear volume of dereferencing that will likely be taking place for operations on this type.

AnthonyWJones
+17  A: 

Contrary to most questions about structs, this actually seems to be a good use of a struct. If the data it contains are value types, and you are going to use a lot of these, a structure would work well.

Some tips:

:: The struct should not be larger than 16 bytes, or you lose the performance advantages.

:: Make the struct immutable. That makes the usage clearer.

Example:

public struct Point3D {

   public float X { get; private set; }
   public float Y { get; private set; }
   public float Z { get; private set; }

   public Point3D(float x, float y, float z) {
      X = x;
      Y = y;
      Z = z;
   }

   public Point3D Invert() {
      return new Point3D(-X, -Y, -Z);
   }

}
Guffa
Great post, took my last upvote today.
Joel Coehoorn
This is probably a good use of the readonly keyword, i.e. instead of declaring X, Y and Z as properties, you could have readonly fields.The advantage would be that you wouldn't break your immutability by mistake.
Ant
+1  A: 

The answer depends on where the objects/values will eventually be stored. If they are to be stored in an untyped collection like ArrayList, then you end up boxing them. Boxing creates an object wrapper for a struct and the footprint is the same as with a class object. On the other hand if you use a typed array like T[] or List, then using structs will only store the actual data for each element with footprint for entire collection only and not its elements.

So structs are more efficient for use in T[] arrays.

agsamek
+1  A: 

As a rule, large arrays of non-aliased (i.e. unshared) data of the same type is best stored in structs for performance since you reduce the number of indirections. (See also when-are-structs-the-answer). The exact performance difference between class and struct depends on your usage. (E.g., in operations, do you only access parts of the struct? Do you do a lot of temporary copying? If the struct is small it's probably always better to use but if it's large, creating temporary copies may slow you down. If you make it immutable you will have to always copy the whole thing to change the value.)

When in doubt, measure.

Since you are interested in possible long-term effects that may not be apparent by such a measurement, be aware that such arrays are likely stored on the large-object heap and should be re-used instead of destroyed and re-allocated. (see CRL Inside Out: Large Object Heap Uncovered.)

When passing larger-size structs in calls you might want to pass them with the ref argument to avoid copying.

ILoveFortran