Pregunta

Tengo una práctica de codificación cuestionable.

Cuando necesito recorrer una pequeña lista de elementos cuyo límite de recuento está por debajo 32000, Yo suelo Int16 para mi i tipo de variable en lugar de Integer.Hago esto porque asumo que usaré el Int16 es más eficiente que un completo Integer.

¿Me equivoco?¿No existe una diferencia de rendimiento efectiva entre usar un Int16 vs un Integer?¿Debo dejar de usar? Int16 y solo quédate con Integer para todas mis necesidades de conteo/iteración?

¿Fue útil?

Solución

Según la referencia a continuación, el tiempo de ejecución optimiza el rendimiento de Int32 y los recomienda para contadores y otras operaciones a las que se accede con frecuencia.

Del libro: MCTS Kit de entrenamiento a su propio ritmo (examen 70-536): Microsoft & # 174; .NET Framework 2.0 & # 8212; Fundación para el Desarrollo de Aplicaciones

Capítulo 1: " Fundamentos del marco "
Lección 1: & Quot; Uso de tipos de valor & Quot;

  

Mejores prácticas: optimización del rendimiento   con tipos incorporados

     

El tiempo de ejecución optimiza el rendimiento de los tipos enteros de 32 bits (Int32 y UInt32), por lo tanto, use esos tipos para contadores y otras variables integrales a las que se accede con frecuencia.

     

Para operaciones de punto flotante, Double es el tipo más eficiente porque esas operaciones están optimizadas por hardware.

Además, la Tabla 1-1 en la misma sección enumera los usos recomendados para cada tipo. Relevante para esta discusión:

  • Int16 - Interoperación y otros usos especializados
  • Int32 - Números enteros y contadores
  • Int64 - Grandes números enteros

Otros consejos

Debe casi siempre usar Int32 o Int64 (y, no, no obtiene crédito al usar UInt32 o UInt64) al recorrer una matriz o colección por índice.

La razón más obvia de que es menos eficiente es que todos los índices de matriz y colección que se encuentran en el BCL toman Int16 s, por lo que una conversión implícita siempre sucederá en el código que intenta usar Byte s como índice.

La razón menos obvia (y la razón por la que las matrices toman SByte como índice) es que la especificación CIL dice que todos los valores de la pila de operaciones son ya sea UInt16 o short i = 0 . Cada vez que carga o almacena un valor en cualquier otro tipo de entero (i<32000, i++, <=>, <=>, <=> o <=>), hay una operación de conversión implícita involucrada. Los tipos sin signo no tienen penalización por cargar, pero por almacenar el valor, esto equivale a un truncamiento y una posible verificación de desbordamiento. Para los tipos firmados, cada carga los signos de extensión, y cada signo de tienda se contrae (y tiene una posible comprobación de desbordamiento).

El lugar en el que esto te va a doler más es el bucle en sí, no los accesos a la matriz. Por ejemplo, tome este bucle de aspecto inocente:

for (short i = 0; i < 32000; i++) {
    ...
}

Se ve bien, ¿verdad? No! Básicamente, puede ignorar la inicialización (<=>) ya que solo ocurre una vez, pero las partes de comparación (<=>) e incremental (<=>) ocurren 32000 veces. Aquí hay un código de pesudo para el aspecto de esta cosa a nivel de máquina:

  Int16 i = 0;
LOOP:
  Int32 temp0 = Convert_I16_To_I32(i); // !!!
  if (temp0 >= 32000) goto END;
  ...
  Int32 temp1 = Convert_I16_To_I32(i); // !!!
  Int32 temp2 = temp1 + 1;
  i = Convert_I32_To_I16(temp2); // !!!
  goto LOOP;
END:

Hay 3 conversiones que se ejecutan 32000 veces. Y podrían haberse evitado por completo simplemente usando un <=> o <=>.

Actualización: como dije en el comentario, ahora, de hecho, escribí una publicación de blog sobre este tema, Tipos de datos integrales .NET y usted

Int16 en realidad puede ser menos eficiente porque las instrucciones x86 para acceso a palabras ocupan más espacio que las instrucciones para acceso a dword. Dependerá de lo que haga el JIT. Pero pase lo que pase, es casi seguro que no sea más eficiente cuando se usa como variable en una iteración.

Lo contrario es cierto.

Los enteros de 32 (o 64) bits son más rápidos que int16. En general, el tipo de datos nativo es el más rápido.

Int16 es bueno si desea que sus estructuras de datos sean lo más esbeltas posible. Esto ahorra espacio y puede mejorar el rendimiento.

Cualquier diferencia de rendimiento será tan pequeña en el hardware moderno que, a todos los efectos, no hará ninguna diferencia. Intente escribir un par de arneses de prueba y ejecútelos unos cientos de veces, tome el tiempo promedio de finalización del ciclo y verá lo que quiero decir.

Puede tener sentido desde una perspectiva de almacenamiento si tiene recursos muy limitados: sistemas integrados con una pila pequeña, protocolos de cable diseñados para redes lentas (por ejemplo, GPRS, etc.), etc.

Nunca asumas la eficiencia.

Lo que es o no más eficiente variará de un compilador a otro y de plataforma a plataforma. A menos que haya probado esto, no hay forma de saber si int16 o int son más eficientes.

Me quedaría con ints a menos que se encuentre con un problema de rendimiento comprobado que al usar soluciones de int16.

Use Int32 en máquinas de 32 bits (o Int64 en máquinas de 64 bits) para un rendimiento más rápido. Utilice un tipo entero más pequeño si está realmente preocupado por el espacio que ocupa (aunque puede ser más lento).

Los otros aquí son correctos, solo use menos que Int32 (para código de 32 bits) / Int64 (para código de 64 bits) si lo necesita para requisitos de almacenamiento extremos, o para otro nivel de aplicación en un campo de objeto de negocio (por supuesto, en este caso aún debe tener una validación de nivel de propiedad)

Y, en general, no se preocupe por la eficiencia hasta que haya un problema de rendimiento. Y en ese caso, perfílalo. Y si adivina & Amp; verificar con ambas formas mientras que la creación de perfiles no le ayuda lo suficiente, verifique el código IL.

Buena pregunta sin embargo. Estás aprendiendo más sobre cómo el compilador hace lo suyo. Si desea aprender a programar de manera más eficiente, sería una gran idea aprender los conceptos básicos de IL y cómo los compiladores de C # / VB hacen su trabajo.

No puedo imaginar que haya una ganancia de rendimiento significativa en Int16 vs. int.

Guarda algunos bits en la declaración de variable.

Y definitivamente no vale la pena cuando las especificaciones cambian y todo lo que estás contando puede ir por encima de 32767 ahora y descubres que cuando tu aplicación comienza a lanzar excepciones ...

No hay una ganancia de rendimiento significativa al usar un tipo de datos más pequeño que Int32, de hecho, leí en alguna parte que usar Int32 será más rápido que Int16 debido a la asignación de memoria

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top