Sé que las excepciones tienen una penalización de rendimiento, y que generalmente es más eficiente intentar y evitar excepciones que dejar caer un gran try/catch en todo, pero ¿qué pasa con el bloque Try? ? ¿Cuál es el costo de simplemente declarar un try/catch, incluso si nunca arroja una excepción?Costo de rendimiento de 'probar' en C#
Respuesta
El costo de rendimiento de try es muy pequeño. El principal costo del manejo de excepciones es obtener el seguimiento de la pila y otros metadatos, y ese es un costo que no se paga hasta que realmente tenga que lanzar una excepción.
Pero esto variará según el idioma y la implementación. ¿Por qué no escribir un bucle simple en C# y cronometrarlo usted mismo?
Sí. Pruébalo es efectivamente gratis porque básicamente se maneja con metadatos que realmente solo se inspeccionan cuando se lanza la excepción. –
Es posible que desee leer sobre el manejo estructurado de excepciones. Es la implementación de excepciones de Window y se usa en .NET.
Un dicho común es que las excepciones son caros cuando son capturados - sin torcer. Esto es porque más de la recopilación de metadatos de excepción (como obtener un seguimiento de pila, etc.) solo sucede realmente en el lado de try-catch (no en el lado throw).
El desenrollado de la pila es realmente bastante rápido: el CLR sube la pila de llamadas y solo presta atención a los bloques finalmente encontrados; en ningún punto en un bloque try-finally puro el intento intenta "completar" una excepción (sus metadatos, etc.).
Por lo que recuerdo, cualquier intento de captura con filtros (como "catch (FooException) {}") es igual de caro, incluso si no hacen nada con la excepción.
Me atrevería a decir que un método (lo llaman CatchesAndRethrows) con el siguiente bloque:
try
{
ThrowsAnException();
}
catch
{
throw;
}
podría resultar en un paseo rápido pila en un método - como por ejemplo:
try
{
CatchesAndRethrows();
}
catch (Exception ex) // The runtime has already done most of the work.
{
// Some fancy logic
}
Algunos números:
With: 0.13905ms
Without: 0.096ms
Percent difference: 144%
Aquí está el punto de referencia que ejecuté (recuerde, modo de lanzamiento - ejecute sin deb ug):
static void Main(string[] args)
{
Stopwatch withCatch = new Stopwatch();
Stopwatch withoutCatch = new Stopwatch();
int iterations = 20000;
for (int i = 0; i < iterations; i++)
{
if (i % 100 == 0)
{
Console.Write("{0}%", 100 * i/iterations);
Console.CursorLeft = 0;
Console.CursorTop = 0;
}
CatchIt(withCatch, withoutCatch);
}
Console.WriteLine("With: {0}ms", ((float)(withCatch.ElapsedMilliseconds))/iterations);
Console.WriteLine("Without: {0}ms", ((float)(withoutCatch.ElapsedMilliseconds))/iterations);
Console.WriteLine("Percent difference: {0}%", 100 * withCatch.ElapsedMilliseconds/withoutCatch.ElapsedMilliseconds);
Console.ReadKey(true);
}
static void CatchIt(Stopwatch withCatch, Stopwatch withoutCatch)
{
withCatch.Start();
try
{
FinallyIt(withoutCatch);
}
catch
{
}
withCatch.Stop();
}
static void FinallyIt(Stopwatch withoutCatch)
{
try
{
withoutCatch.Start();
ThrowIt(withoutCatch);
}
finally
{
withoutCatch.Stop();
}
}
private static void ThrowIt(Stopwatch withoutCatch)
{
throw new NotImplementedException();
}
Creo que OP preguntó sobre el impacto en el rendimiento cuando NO se lanzan excepciones. – Shimmy
En realidad, hace un par de meses que estaba creando una aplicación Web ASP.NET, y accidentalmente envuelto un bloque try/catch con un bucle muy largo. Aunque el ciclo no generaba todas las excepciones, tardaba demasiado tiempo en terminar. Cuando volví y vi el try/catch envuelto por el loop, lo hice al revés, envolví el loop en el bloque try/catch. El rendimiento mejoró MUCHO. Puede probar esto por su cuenta: haga algo como
int total;
DateTime startTime = DateTime.Now;
for(int i = 0; i < 20000; i++)
{
try
{
total += i;
}
catch
{
// nothing to catch;
}
}
Console.Write((DateTime.Now - startTime).ToString());
Y luego saque el bloque try/catch. ¡Verás una gran diferencia!
Hmmm. Acabo de probar esto en .Net 2.0 (usando un 'Cronómetro'). 50000 pruebas de 20000 iteraciones de bucle tardan 4184ms sin 'try-catch', 4363ms con' try-catch'. Esa es una diferencia increíblemente pequeña. Tal diferencia será aún menos visible si cada iteración realmente está haciendo algo más allá de una simple operación de suma. Llegué a resultados similares con y sin depuración. – Brian
Para ver lo que realmente cuesta, puede ejecutar el código a continuación. Se necesita una matriz bidimensional simple y genera coordenadas aleatorias que están fuera de rango. Si su excepción solo ocurre una vez, por supuesto no la notará. Mi ejemplo se hace para enfatizar lo que significará al hacer esto varias miles de veces, y qué capturar una excepción vs implementar una prueba simple te salvará.
const int size = 1000;
const int maxSteps = 100000;
var randomSeed = (int)(DateTime.UtcNow - new DateTime(1970,1,1,0,0,0).ToLocalTime()).TotalMilliseconds;
var random = new Random(randomSeed);
var numOutOfRange = 0;
var grid = new int[size,size];
var stopwatch = new Stopwatch();
Console.WriteLine("---Start test with exception---");
stopwatch.Reset();
stopwatch.Start();
for (int i = 0; i < maxSteps; i++)
{
int coord = random.Next(0, size * 2);
try
{
grid[coord, coord] = 1;
}
catch (IndexOutOfRangeException)
{
numOutOfRange++;
}
}
stopwatch.Stop();
Console.WriteLine("Time used: " + stopwatch.ElapsedMilliseconds + "ms, Number out of range: " + numOutOfRange);
Console.WriteLine("---End test with exception---");
random = new Random(randomSeed);
stopwatch.Reset();
Console.WriteLine("---Start test without exception---");
numOutOfRange = 0;
stopwatch.Start();
for (int i = 0; i < maxSteps; i++)
{
int coord = random.Next(0, size * 2);
if (coord >= grid.GetLength(0) || coord >= grid.GetLength(1))
{
numOutOfRange++;
continue;
}
grid[coord, coord] = 1;
}
stopwatch.Stop();
Console.WriteLine("Time used: " + stopwatch.ElapsedMilliseconds + "ms, Number out of range: " + numOutOfRange);
Console.WriteLine("---End test without exception---");
Console.ReadLine();
Ejemplo de salida de este código:
---Start test with exception---
Time used: 3228ms, Number out of range: 49795
---End test with exception---
---Start test without exception---
Time used: 3ms, Number out of range: 49795
---End test without exception---
- 1. Costo de rendimiento de una Memcopy en C/C++
- 2. Costo de métodos de alineación en C#
- 3. Costo de rendimiento de las comparaciones de tipos
- 4. ¿El rendimiento de Python vale la pena el costo?
- 5. costo de rendimiento de un bloque try/catch
- 6. ¿Cuál es el costo de rendimiento de llamar a Thread.isInterrupted()?
- 7. Cómo evitar el costo de rendimiento del desbordamiento: ¿oculto?
- 8. Costo de desarrollo versus costo de mantenimiento
- 9. Costo de manejadores de excepciones en Python
- 10. Costo de generar una intención en android
- 11. Costo de usar referencias débiles en Java
- 12. Costo de incluir archivos de encabezado en Objective-C
- 13. Costo de rendimiento de creación de perfiles de una aplicación web en producción
- 14. ¿El costo de rendimiento de la codificación de "desarrollo impulsado por excepciones" en Java?
- 15. ¿El costo de rendimiento de usar ref en lugar de devolver los mismos tipos?
- 16. Velocidad/costo de almacenamiento local
- 17. Costo del envío de mensajes en Objective-C
- 18. ¿Costo para GC de usar referencias débiles en C#?
- 19. ¿Existe un costo de rendimiento significativo para DynamicResource en lugar de StaticResource?
- 20. costo de utilizar parámetros repetidos
- 21. ¿Cómo probar el rendimiento de una aplicación de Android?
- 22. Prueba de unidad C++ para probar el rendimiento (punto de referencia sintético)
- 23. costo de operación atómica
- 24. Costo de sincronización
- 25. ¿Cuál es el costo de rendimiento de asignar un único valor de cadena usando + '
- 26. C++ probar experiencias de captura
- 27. ¿Diferencia de rendimiento extraña de C++?
- 28. Rendimiento en C#
- 29. Copia de archivo de rendimiento en C#?
- 30. Rendimiento de comparación de cadenas en C#
usted es la única persona que puede responder a esta pregunta. Usted es la única persona que sabe qué tipo de hardware y software está utilizando, usted es la única persona que sabe qué métricas de rendimiento son relevantes para su cliente, y así sucesivamente. Escriba algunos puntos de referencia realistas, pruébelos con hardware realista y luego sabrá la respuesta. Cualquier persona que intente responder la pregunta por usted está adivinando o describiendo las características de rendimiento en sus máquinas, para sus clientes, no para usted. De cualquier manera, esos no son los datos que necesita. –
@Eric - Bien dicho. –