¿Por qué debería usar int en lugar de un byte o abreviar en C #

He encontrado algunos hilos con respecto a este tema. La mayoría de las personas parece favorecer el uso de int en su código c # en todo el tablero, incluso si un byte o smallint manejaría los datos a menos que sea una aplicación móvil. No entiendo por qué. ¿No tiene más sentido definir su tipo de datos C # como el mismo tipo de datos que estaría en su solución de almacenamiento de datos?

Mi premisa: si estoy usando un conjunto de datos tipeados, clases de Linq2SQL, POCO, de una forma u otra me encontraré con problemas de conversión del tipo de datos del comstackdor si no mantengo mis tipos de datos sincronizados en mis niveles. Realmente no me gusta hacer el System.Convert todo el tiempo solo porque era más fácil de usar int en todo el tablero en el código c #. Siempre utilicé el tipo de datos más pequeño que sea necesario para manejar los datos en la base de datos y en el código, para mantener limpia mi interfaz con la base de datos. Así que apostaría a que el 75% de mi código C # usa byte o short en lugar de int, porque eso es lo que hay en la base de datos.

Posibilidades: ¿Esto significa que la mayoría de las personas que usan int para todo en código también usan el tipo de datos int para sus tipos de datos de almacenamiento sql y no les importa el tamaño general de su base de datos, o lo hacen en el código cuando sea aplicable?

Por qué me importa: he trabajado por mi cuenta para siempre y solo quiero estar familiarizado con las mejores prácticas y las convenciones de encoding estándar.

Solo llevo 6 años de retraso, pero quizás pueda ayudar a alguien más.

Aquí hay algunas pautas que usaría:

  • Si existe la posibilidad de que los datos no se ajusten en el futuro, utilice el tipo int más grande.
  • Si la variable se utiliza como un campo de estructura / clase, de forma predeterminada se rellenará para ocupar los 32 bits completos de todos modos, por lo que el uso de byte / int16 no ahorrará memoria.
  • Si la variable tiene una vida corta, entonces (como dentro de una función), los tipos de datos más pequeños no ayudarán mucho.
  • “byte” o “char” a veces puede describir los datos mejor y puede hacer una verificación de tiempo de comstackción para asegurarse de que no se le asignen valores mayores por accidente. por ejemplo, si almacena el día del mes (1-31) usando un byte y trata de asignarle 1000, se producirá un error.
  • Si la variable se usa en una matriz de aproximadamente 100 o más, usaría el tipo de datos más pequeño, siempre que tenga sentido.
  • las matrices byte e int16 no son tan seguras como una int (primitiva).

Un tema que nadie mencionó es el limitado caché de la CPU. Los progtwigs más pequeños se ejecutan más rápido que los más grandes porque la CPU puede acomodar más del progtwig en las cachés L1 / L2 / L3 más rápidas.

El uso del tipo int puede dar como resultado menos instrucciones de CPU, sin embargo, también forzará que un mayor porcentaje de la memoria de datos no encaje en la memoria caché de la CPU. Las instrucciones son baratas de ejecutar. Los núcleos de CPU modernos pueden ejecutar de 3 a 7 instrucciones por ciclo de reloj; sin embargo, una sola falta de caché por otro lado puede costar de 1000 a 2000 ciclos de reloj porque tiene que llegar hasta la RAM.

Cuando la memoria se conserva, también da como resultado que el rest de la aplicación tenga un mejor rendimiento porque no se extrae de la memoria caché.

Hice una prueba de sum rápida al acceder a los datos aleatorios en orden aleatorio usando una matriz de bytes y una matriz int.

 const int SIZE = 10000000, LOOPS = 80000; byte[] array = Enumerable.Repeat(0, SIZE).Select(i => (byte)r.Next(10)).ToArray(); int[] visitOrder = Enumerable.Repeat(0, LOOPS).Select(i => r.Next(SIZE)).ToArray(); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); int sum = 0; foreach (int v in visitOrder) sum += array[v]; sw.Stop(); 

Aquí están los resultados en el tiempo (tics): (x86, modo de lanzamiento, sin depurador, .NET 4.5, I7-3930k) (más pequeño es mejor)

 ________________ Array Size __________________ 10 100 1K 10K 100K 1M 10M byte: 549 559 552 552 568 632 3041 int : 549 566 552 562 590 1803 4206 
  • ¡el acceso aleatorio a los elementos de 1M mediante byte en mi CPU tuvo un aumento del 285% en el rendimiento!
  • Cualquier cosa por debajo de 10,000 fue apenas perceptible.
  • int nunca fue más rápido que el byte para esta prueba de sum básica.
  • Estos valores serán muy diferentes con diferentes CPU con diferentes tamaños de caché.

Una nota final: a veces miro el marco .NET ahora de código abierto para ver qué hacen los expertos de Microsoft. El framework .NET usa byte / int16 sorprendentemente poco. No pude encontrar ninguno en realidad.

Tendría que lidiar con unas BILLONES filas antes de que esto haga una diferencia significativa en términos de capacidad de almacenamiento. Digamos que tiene tres columnas, y en lugar de usar un tipo de base de datos equivalente a bytes, usa un int-equivalent.

Eso nos da 3 (columnas) x 3 (bytes adicionales) por fila, o 9 bytes por fila.

Esto significa que, para “unos pocos millones de filas” (digamos tres millones), ¡está consumiendo 27 megabytes adicionales de espacio en disco! Afortunadamente, como ya no vivimos en la década de 1970, no deberías preocuparte por esto 🙂

Como se dijo anteriormente, detenga la micro-optimización: el rendimiento alcanzado al convertir a / desde diferentes tipos de números enteros va a afectarle mucho, mucho más que los costos de ancho de banda / espacio de disco, a menos que tenga que lidiar con muy, muy, mucho conjuntos de datos.

En su mayor parte, no’.

A menos que sepa de antemano que va a tratar con cientos de millones de filas, se trata de una micro-optimización.

Haz lo que mejor se adapte al modelo de Dominio. Más tarde, si tiene problemas de rendimiento, punto de referencia y perfil para señalar dónde están ocurriendo.

No es que no creyera en Jon Grant y otros, pero tenía que verlo por nuestra cuenta con nuestra “mesa de millones de filas”. La mesa tiene 1,018,000. Convertí 11 columnas tinyint y 6 columnas smallint en int, ya había 5 int y 3 smalldatetimes. 4 índices diferentes usaron una combinación de varios tipos de datos, pero obviamente los nuevos índices ahora están usando columnas int.

Realizar los cambios solo me costó 40 mb al calcular el uso del disco de la tabla base sin índices. Cuando agregué los índices nuevamente en el cambio general, solo hubo 30 mb de diferencia en general. Así que me sorprendió porque pensé que el tamaño del índice sería más grande.

Entonces, ¿vale la pena la molestia de 30 Mb de usar todos los tipos de datos diferentes, de ninguna manera! Me voy a tierra INT, gracias a todos por volver a configurar este progtwigdor anal retentivo en la recta y feliz vida feliz de no más conversiones de enteros … ¡yippeee!

Si int se usa en todas partes, no se requieren conversiones ni conversiones. Esa es una mayor inversión para la pelota que la memoria que ahorrará al usar múltiples tamaños enteros.

Simplemente hace la vida más simple.

El tiempo de ejecución .NET está optimizado para Int32. Ver discusión previa en .NET Integer vs Int16?