¿Es un try and catch que no arroja una excepción más eficiente que un condicional?

8

Me encontré con este ejemplo recientemente:

Si 999 de cada 1,000 veces no se lanzará una excepción, la excepción solo se genera una vez. Por otro lado, un condicional se habría llamado innecesariamente 999 veces, por lo tanto, en este caso, la excepción es superior.

En este caso, es C #, pero, en general, ¿es esto cierto? Anteriormente había asumido que las declaraciones try / catch tenían sus propios gastos generales que equivaldrían al tiempo dedicado a manejar un condicional.

Por supuesto, solo lanzar bloques try / catch en cualquier lugar donde normalmente iría un condicional sería una forma terrible de codificar, pero en términos de recursos, ¿esta afirmación se mantiene?

Jane Panda
fuente
¿Cómo implementa el compilador try / catch? Sospecho que es un poco más complicado que un simple if ().
Dan Pichelman
8
Pruébalo. Realmente, pruébalo. ¿Por qué crees algo que dijo una persona al azar en Internet? Saber cómo los elementos comunes en su idioma de elección comparan el rendimiento bien vale la pena el esfuerzo limitado de realizar un experimento cuidadoso, una vez.
Kilian Foth
Sentí que escribir una comparación de rendimiento es una tarea muy fácil de estropear, especialmente una abstracta; también el ejemplo es de un libro de texto de C #
Jane Panda
2
Haré el comentario obligatorio "escriba código legible y no optimice prematuramente".
djechlin
1
@djechlin Alguien tuvo que hacerlo; )
Jane Panda

Respuestas:

4

En general, es cierto para los compiladores de calidad comercial. Sin embargo, los condicionales pueden lograr eficiencias similares utilizando assume(false)anotaciones de estilo. La optimización guiada por perfil puede vencer a ambos.

La razón subyacente es que los buenos compiladores pueden generar código más eficiente haciendo suposiciones correctas sobre la probabilidad de que se ejecute el código. Dado que la convención es que las excepciones son excepcionales, la mayoría de los compiladores (en ausencia de datos de generación de perfiles) generarán un código óptimo cuando las excepciones son realmente raras.

Por ejemplo, el código de manejo de excepciones se puede colocar en su propio segmento, y solo se paginará cuando ocurra la primera excepción. Esto significa que el caché de la CPU se puede usar de manera más eficiente, almacenando solo código no excepcional.

MSalters
fuente
Y los compiladores dinámicos, como por ejemplo los que se encuentran en casi todos los motores JavaScript, JVM e implementaciones de Smalltalk, ni siquiera necesitan hacer suposiciones sobre la probabilidad de ramificaciones, solo pueden contarlos. Eso es como PGO con esteroides: volver a perfilar y volver a optimizar una y otra y otra vez, utilizando la carga de trabajo real que se está ejecutando en este momento para guiar la optimización del código que se está ejecutando en este momento .
Jörg W Mittag
4

Hay escenarios para usar try / catch y otros para usar condicionales.

El uso de un try / catch no daña el rendimiento como se describe ampliamente aquí

El costo total de un intento ... el bloque catch que nunca maneja una excepción son unos pocos bytes de memoria

Más allá del rendimiento, el manejo adecuado de excepciones es importante. Lo último que desea es que se muestren los errores no detectados a un usuario, el rendimiento defectuoso o la aplicación que se cuelga después de que se encuentra un problema.

Erich
fuente
3
El rendimiento de +1 no es lo único importante de lo que preocuparse o podríamos
deshacernos de las
2
Esa es una gran lectura con respecto a las excepciones.
Jane Panda
-1

Un ejemplo de un mejor rendimiento usando try / catch en lugar de un condicional es cuando se trata de diccionarios, cuando se pregunta si contiene la clave es O (n) en lugar de solo intentar acceder / agregar la clave y detectar la posible excepción.

try
{
    dict.Add(key, val);
}
catch (Exception)
{

    dict[key] = val;
}
Enrique Medina
fuente
Wow, si esto es cierto, ¡estoy realmente sorprendido! Tiene una referencia?
55
-1. No hagas esto. Si le preocupa la sobrecarga de rendimiento de verificar si la clave existe, use TryGetValue () en su lugar. msdn.microsoft.com/en-us/library/bb347013.aspx
riwalk
gracias por señalar que, lo menos que quiero es aconsejar una mala práctica. Sin embargo, he estado usando esto durante mucho tiempo, buen habbit que se volvió obsoleto, supongo. De todos modos, mi punto era mostrar que hay escenarios en los que capturar una excepción podría ser una opción mejor que preguntar si es válido hacer algo.
Enrique Medina