Las sentencias de cambio suelen ser más rápidas que las sentencias if-else-if equivalentes (como, por ejemplo, se describe en este artículo ) debido a las optimizaciones del compilador.
¿Cómo funciona realmente esta optimización? ¿Alguien tiene una buena explicación?
c#
performance
switch-statement
if-statement
Dirk Vollmar
fuente
fuente
Respuestas:
El compilador puede crear tablas de salto cuando corresponda. Por ejemplo, cuando usa el reflector para mirar el código producido, verá que para interruptores grandes en cadenas, el compilador generará código que usa una tabla hash para enviarlos. La tabla hash utiliza las cadenas como claves y delega los
case
códigos como valores.Esto tiene un mejor tiempo de ejecución asintótico que muchos
if
pruebas y en realidad es más rápido incluso para relativamente pocas cadenas.fuente
Esta es una ligera simplificación, como suele ocurrir con cualquier compilador moderno que
if..else if ..
secuencia que una persona podría convertir trivialmente en una declaración de cambio, el compilador también lo hará. Pero solo para agregar diversión extra, el compilador no está restringido por la sintaxis, por lo que puede generar declaraciones similares a "switch" internamente que tienen una combinación de rangos, objetivos únicos, etc., y pueden (y lo hacen) hacer esto tanto para switch como para if. otras declaraciones.De todos modos, una extensión de la respuesta de Konrad es que el compilador puede generar una tabla de salto, pero eso no está necesariamente garantizado (ni es deseable). Por una variedad de razones, las tablas de salto hacen cosas malas a los predictores de rama en los procesadores modernos, y las tablas mismas hacen cosas malas al comportamiento de la caché, por ejemplo.
Si un compilador generara realmente una tabla de salto para esto, probablemente sería más lento que el
if..else if..
código de estilo alternativo debido a que la tabla de salto anula la predicción de rama.fuente
Es posible que las estadísticas de no coincidencia no sean buenas.
Si realmente descarga la fuente, se sabe que los valores de no coincidencia son 21, tanto en el caso if como en el switch. Un compilador debería poder abstraerse, sabiendo qué sentencia debería ejecutarse en todo momento, y una CPU debería poder predecir bifurcaciones correctamente.
El caso más interesante es cuando no todos los casos se rompen, en mi opinión, pero ese puede no haber sido el alcance del experimento.
fuente
Las declaraciones switch / case pueden ser típicamente más rápidas en un nivel de profundidad, pero cuando comienza a entrar en 2 o más, las declaraciones switch / case comienzan a tomar 2-3 veces más que las declaraciones if / else anidadas.
Este artículo tiene algunas comparaciones de velocidad que destacan las diferencias de velocidad cuando se anidan tales declaraciones.
Por ejemplo, según sus pruebas, muestra un código como el siguiente:
terminó en la mitad del tiempo que tardó en ejecutarse la instrucción switch / case equivalente:
Sí, es un ejemplo rudimentario, pero ilustra el punto.
Entonces, una conclusión podría ser usar switch / case para tipos simples que tienen solo un nivel de profundidad, pero para comparaciones más complejas y múltiples niveles anidados, use las construcciones clásicas if / else?
fuente
La única ventaja del caso if over es cuando hay un aumento notable de la frecuencia de ocurrencia del primer caso.
No estoy seguro de dónde está exactamente el umbral, pero uso la sintaxis de casos a menos que el primer "casi siempre" pase la primera prueba.
fuente