Struct vs Class for long lived objects

2019-02-04 12:19发布

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?

6条回答
虎瘦雄心在
2楼-- · 2019-02-04 12:28

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.

查看更多
Explosion°爆炸
3楼-- · 2019-02-04 12:34

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.

查看更多
劳资没心,怎么记你
4楼-- · 2019-02-04 12:40

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);
   }

}
查看更多
戒情不戒烟
5楼-- · 2019-02-04 12:46

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.

查看更多
三岁会撩人
6楼-- · 2019-02-04 12:47

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.

查看更多
我只想做你的唯一
7楼-- · 2019-02-04 12:48

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.

查看更多
登录 后发表回答