¿De qué forma ralentizan las excepciones de C ++ el código cuando no se emiten excepciones?

He leído que hay una sobrecarga en el uso de excepciones de C ++ para el manejo de excepciones en lugar de, por ejemplo, verificar los valores de retorno. Solo estoy hablando de gastos generales incurridos cuando no se lanza ninguna excepción. También asumo que necesitaría implementar el código que realmente verifica el valor de retorno y hace lo correcto, cualquiera que sea el equivalente a lo que hubiera hecho el bloque catch. Y, tampoco es justo comparar el código que arroja objetos de excepción con 45 variables de estado dentro del código que devuelve un número entero negativo para cada error.

No estoy tratando de crear un caso a favor o en contra de las excepciones de C ++ basándose únicamente en cuál se podría ejecutar más rápido. Escuché que alguien presentó el caso recientemente de que el código que utiliza excepciones debe ejecutarse tan rápido como el código basado en códigos de retorno, una vez que se tiene en cuenta todo el código de contabilidad adicional que se necesitaría para verificar los valores devueltos y manejar los errores. ¿Qué me estoy perdiendo?

Hay un costo asociado con el manejo de excepciones en algunas plataformas y con algunos comstackdores.

A saber, Visual Studio, al crear un destino de 32 bits, registrará un controlador en cada función que tenga variables locales con un destructor no trivial. Básicamente, establece un controlador try/finally .

La otra técnica, empleada por gcc y Visual Studio dirigida a 64 bits, solo incurre en sobrecarga cuando se lanza una excepción (la técnica implica atravesar la stack de llamadas y la búsqueda de tablas). En los casos en que rara vez se lanzan excepciones, esto puede conducir a un código más eficiente, ya que no es necesario procesar los códigos de error.

Solo intente / capture y pruebe / excepto bloquear, tome algunas instrucciones para configurarlo. La sobrecarga generalmente debe ser insignificante en todos los casos, excepto en los bucles más pesados. Pero normalmente no usaría try / catch / excepto en un bucle interno de todos modos.

Aconsejaría no preocuparme por esto, y usar un generador de perfiles para optimizar tu código donde sea necesario.

Es completamente dependiente de la implementación, pero muchas implementaciones recientes tienen muy poca o ninguna sobrecarga de rendimiento cuando no se lanzan excepciones. De hecho, tienes razón. Comprobar correctamente los códigos de retorno de todas las funciones en el código que no usa excepciones puede ser más lento y no hacer nada por el código utilizando excepciones.

Por supuesto, necesitaría medir el rendimiento para sus requisitos particulares para estar seguro.

Hay algunos gastos generales con excepciones (como se señaló en las otras respuestas).

Pero no tienes mucha opción hoy en día. Intente desactivar las excepciones en su proyecto y asegúrese de que TODOS los códigos y bibliotecas dependientes puedan comstackrse y ejecutarse sin él.

¿Funcionan con excepciones deshabilitadas?

Supongamos que lo hacen! Luego compare algunos casos, pero tenga en cuenta que debe establecer un interruptor de comstackción “deshabilitar excepciones”. Sin ese interruptor, usted todavía tiene la sobrecarga, incluso si el código nunca arroja excepciones.

Solo la sobrecarga es ~ 6 instrucciones que agregan 2 SEH al inicio de la función y los dejan al final. No importa cuántas try / catch tengas en un hilo, siempre es lo mismo.

Además, ¿qué es esto sobre las variables locales? Oigo gente que siempre se queja de ellos cuando usa try / catch. No lo entiendo, porque los deconstructores eventualmente se llamarían de todos modos. Además, no debe permitir que una excepción suba más de 1 a 3 llamadas.

Tomé el código de prueba de Chip Uni y lo amplié un poco. Divido el código en dos archivos fuente (uno con excepciones, y otro sin). Hice que cada punto de referencia se ejecutara 1000 veces, y utilicé clock_gettime() con CLOCK_REALTIME para registrar las horas de inicio y fin de cada iteración. Luego calculé la media y la varianza de los datos. Ejecuté esta prueba con versiones de 64 bits de g ++ 5.2.0 y clang ++ 3.7.0 en una caja Intel Core i7 con 16 GB de RAM que ejecuta ArchLinux con kernel 4.2.5-1-ARCH. Puede encontrar el código expandido y los resultados completos aquí .

g ++

Sin excepciones

  • Promedio: 30,022,994 nanosegundos
  • Desviación estándar: 1.25327e + 06 nanosegundos

Excepciones

  • Promedio: 30,025,642 nanosegundos
  • Desviación estándar: 1.83422e + 06 nanosegundos

clang ++

Sin excepciones

  • Promedio: 20,954,657 nanosegundos
  • Desviación estándar: 426,662 nanosegundos

Excepciones

  • Promedio: 23,916,638 nanosegundos
  • Desviación estándar: 1.72583e + 06 nanosegundos

Las excepciones de C ++ solo incurren en una penalización de rendimiento no trivial con clang ++, e incluso esa penalización es solo ~ 14%.