2010-03-13 12 views
10

Estoy estudiando struct; algunos libros recomiendan crear struct si tiene un tamaño de instancia menor que 16 bytes.¿Por qué es mejor struct con menos de 16 bytes?

¿Por qué?

Gracias por cualquier respuesta.

+0

duplicado de http://stackoverflow.com/questions/1082311/why-should-a-net-struct-be-less-than-16-bytes –

+0

También un engañado de http://stackoverflow.com/questions/2407691/c-struct-design-why-16-byte-is-recommended-size/2407869 # 2407869 – slugster

Respuesta

28

Es porque 16 bytes es el umbral donde el compilador comienza a copiar las estructuras como bloque de memoria en lugar de usar una o dos instrucciones de movimiento simples.

El compilador optimiza la copia de estructuras cuando son pequeñas. Una estructura que es, por ejemplo, ocho bytes se puede copiar como un único valor de 64 bits. Una estructura de 16 bytes puede copiarse como uno o dos valores singulares (según la arquitectura del procesador). Cuando la estructura es más grande que 16 bytes, el compilador no intenta optimizar el movimiento más, y la alternativa es llamar a un método que copia un bloque de memoria.

(Nota: el umbral de 16 bytes puede variar dependiendo de la versión del compilador, parece que intenta optimizar más allá de ese punto en las versiones más nuevas, pero el código optimizado seguirá siendo un montón de instrucciones de movimiento, en comparación a la copia de una referencia a un objeto que sigue siendo una única operación de movimiento)

Editar:.
Este es el resultado de una prueba que hice en mis 64 bits estructuras de copiado sistema de la mitad de mil millones de veces:

struct 4 : 272 ms. 
struct 8 : 235 ms. 
struct 16 : 317 ms. 
struct 32 : 625 ms. 
struct 64 : 1280 ms. 
struct 128 : 4659 ms. 
struct 256 : 8020 ms. 

Como ve, debajo de 16 bytes el tiempo no es lineal, aunque 16 b ytes es cuatro veces más que 4 bytes, no toma cuatro veces más. Por encima de 16 bytes, el tiempo es lineal, por lo que el doble del doble del tiempo. Ahí es donde comenzaría a usar múltiples movimientos. Por encima de 64 bytes hay un salto, donde el tiempo se cuadruplica cuando el tamaño se duplica. Ahí es donde comenzaría a usarse la reserva.

+0

trae un punto de vista brillante – Ricky

+0

¿De dónde viene su punto? – Ricky

+0

@Ricky: He hecho algunas pruebas a lo largo de los años. Agregué un resultado de prueba actual arriba. – Guffa

1

No son exactamente 16 bytes, pero como las estructuras se pasan por valor (copiadas cada vez que se las da a un método, se las asigna, etc.), no deben ser demasiado grandes. Si lo son, pasar cosas por referencia es más barato.

4 años después: respondí esto sabiendo muy poco sobre .NET (todavía no sé mucho sobre él). La respuesta de Guffa es obviamente más correcta cuando se trata de "más o menos de 16 bytes", ya que a ese tamaño un poco de copia no debería importar mucho. Mi respuesta puede ser algo a tener en cuenta al construir enormes estructuras.

+0

Un puntero de 64 bits es aún más económico que 128 bits de struct. Esta respuesta realmente no tiene mucho sentido. – slugster

+2

"Un puntero de 64 bits es aún más económico que 128 bits de struct". ¿Por qué dices eso? La adquisición de un puntero generalmente significa la asignación de un montón y la recolección de basura que es costosa en .NET. Escribir un puntero implica incurrir en una barrera de escritura que también es costosa en .NET. –

+0

@slugster: una referencia de 8 bytes podría copiarse más barata que una estructura de 16 bytes, pero para que una referencia sea útil, debe identificar un objeto en el montón. Crear un objeto Heap con 16 bytes de datos y copiar una referencia un millón de veces podría ser más barato que copiar una estructura de 16 bytes un millón de veces, pero crear un objeto de 16 bytes, copiar la referencia dos veces y abandonarla será mucho más caro que copiar una estructura de 16 bytes dos veces (o probablemente, incluso veinte veces). – supercat

Cuestiones relacionadas