2009-03-03 12 views
13

Cuando necesite tener objetos muy pequeños, digamos que contengan 2 flotantes, y tendrá millones de ellos que no serán "destruidos" de inmediato, se estructura una mejor opción o clases?Struct vs Class para objetos de larga vida

Como en xna como una biblioteca, hay puntos3, etc. como estructuras, pero si necesita mantener esos valores durante mucho tiempo, ¿supondría una amenaza para el rendimiento?

Respuesta

33

Contrariamente a la mayoría de las preguntas sobre las estructuras, esto parece ser un buen uso de una estructura. Si los datos que contiene son tipos de valor y va a usar muchos de estos, una estructura funcionaría bien.

Algunos consejos:

:: La estructura no debe ser mayor que 16 bytes, o se pierden las ventajas de rendimiento.

:: Hace que la estructura sea inmutable. Eso hace que el uso sea más claro.

Ejemplo:

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

} 
+0

Gran publicación, tomó mi último voto hoy. –

+4

Probablemente sea un buen uso de la palabra clave readonly, es decir, en lugar de declarar X, Y y Z como propiedades, podría tener campos de solo lectura. La ventaja sería que no rompería su inmutabilidad por error. – Ant

+0

Es 'myRect = new Rectangle (myRect.X, myRect.Y + 4, myRect.Width, myRect.Height);' realmente más claro que 'myRect.Y + = 4;'? Los métodos * de mutación * para las estructuras son problemáticos, pero los campos expuestos deberían ser la norma en muchos casos. – supercat

2

La gran preocupación es si la memoria está asignada en la pila o en el montón. Las estructuras van en la pila por defecto, y la pila generalmente es mucho más limitada en términos de espacio. Entonces, crear todo un conjunto de estructuras así puede ser un problema.

En la práctica, sin embargo, realmente no creo que sea tan importante. Si tienes tantos de ellos, es probable que sean parte de una instancia de clase (en el montón) en alguna parte.

+1

El espacio de la pila no es una preocupación para las estructuras, ya que rara vez tiene tantas variables locales. Si crea una matriz de estructuras, se asignará en el montón, no en la pila. – Guffa

+0

Creo que ese era mi punto: si tienes ese número, es un problema, pero es poco probable que tengas tantos. –

+0

Si tiene tantas variables, es un problema independientemente de si es una estructura o una clase, ya que las referencias también se asignarán en la pila ... :) – Guffa

1

Los tipos de valor (struct) son buenos para el tipo que no están asignados en montón a menudo, es decir, están en su mayoría contenidos en otra referencia o tipo de valor.

El ejemplo de Vector3 que dio es un ejemplo perfecto. Rara vez tendrá Vector3 colgado en el montón, la mayoría de las veces estará contenido en un tipo que está en sí mismo en el montón, o utilizado como una variable local, en cuyo caso, se asignará en la pila.

+0

Gracias, entonces las estructuras estarán en el montón solo si se usan como una variable local, ¿y nada más? –

+0

No, es al revés. Un tipo de valor como una estructura solo se asigna en la pila si se trata de una variable local. Si es miembro de una clase, se asigna como parte del área de memoria del objeto en el montón. – Guffa

2

Struct parece ser el adecuado para esta aplicación.

Tenga en cuenta que la "necesidad de mantener esos valores" implica su almacenamiento en el montón en alguna parte, probablemente un campo de matriz de una instancia de clase.

Una cosa a tener en cuenta es que esto da como resultado una asignación en el montón de objetos grandes. No está tan claro cómo, en todo caso, este montón se desfragmenta a sí mismo, sin embargo, para objetos muy longevos que tal vez no sea un problema.

El uso de la clase para millones de estos tipos de datos probablemente sea costoso en el volumen de corte de la desreferenciación que probablemente tendrá lugar para operaciones de este tipo.

5

La respuesta depende de donde eventualmente se pueden almacenar los objetos/valores. Si van a almacenarse en una colección sin tipo como ArrayList, entonces terminas encajándolos. El boxeo crea un contenedor de objetos para una estructura y la huella es la misma que con un objeto de clase. Por otro lado, si usa una matriz escrita como T [] o Lista, entonces el uso de estructuras solo almacenará los datos reales para cada elemento con espacio para toda la colección solamente y no sus elementos.

Por lo tanto, las estructuras son más eficientes para su uso en matrices T [].

2

Como regla, grandes matrices sin alias (es decirsin compartir) los datos del mismo tipo se almacenan mejor en estructuras para el rendimiento ya que se reduce el número de indirecciones. (Ver también when-are-structs-the-answer). La diferencia de rendimiento exacta entre clase y estructura depende de su uso. (Por ejemplo, en las operaciones, ¿solo accedes a partes de la estructura? ¿Realizas muchas copias temporales? Si la estructura es pequeña, es probable que siempre sea mejor usarla, pero si es grande, crear copias temporales puede ralentizarte. hazlo inmutable tendrás que copiar siempre todo para cambiar el valor.)

En caso de duda, medir.

Dado que le interesan los posibles efectos a largo plazo que tal medida puede no ser aparente, tenga en cuenta que tales matrices probablemente se almacenen en el montón de objetos grandes y deberían reutilizarse en lugar de destruirse y volverse a utilizar. asignado. (Consulte CRL Inside Out: Large Object Heap Uncovered.)

Al pasar estructuras de mayor tamaño en las llamadas, es posible que desee pasarlas con el argumento ref para evitar copiarlas.