2008-09-04 8 views
14

¿Cuál es la mejor forma de medir la sobrecarga/el rendimiento de la gestión de excepciones en C++?Medición de gastos generales de excepción en C++

Proporcione ejemplos de código independiente.

Me estoy orientando a Microsoft Visual C++ 2008 y gcc.

que necesito para obtener resultados a partir de los siguientes casos:

  1. sobrecarga cuando no hay bloques try/catch
  2. arriba cuando hay bloques try/catch, pero las excepciones no son arrojados
  3. sobrecarga cuando se lanzan excepciones

Respuesta

9

Como sugerencia: no se moleste demasiado con los gastos generales cuando se producen excepciones. Las implementaciones de manejo de excepciones generalmente no hacen que el lanzamiento sea rápido y lento. Está bien, ya que esos casos son, bueno, excepcionales.

Carl

7

Aquí está el código de medición que se me ocurrió. ¿Ves algún problema con eso?

funciona en Linux y Windows hasta ahora, compilar con:

g++ exception_handling.cpp -o exception_handling [ -O2 ] 

o, por ejemplo Visual C++ Express.

para que el caso base ("apoyo excepción eliminado por completo de la lengua"), utilice:

g++ exception_handling.cpp -o exception_handling [ -O2 ] -fno-exceptions -DNO_EXCEPTIONS 

o similares ajustes en MSVC.

Algunos resultados preliminares here. Es probable que todos sean aburridos debido a la carga variable de la máquina, pero dan alguna idea sobre la relativa sobrecarga de manejo de excepciones. (Resumen Ejecutivo: ninguno o poco cuando no se lanzan excepciones, enorme, cuando en realidad se tiran.)

#include <stdio.h> 

// Timer code 

#if defined(__linux__) 
#include <sys/time.h> 
#include <time.h> 

double time() 
{ 
    timeval tv; 
    gettimeofday(&tv, 0); 
    return 1.0 * tv.tv_sec + 0.000001 * tv.tv_usec; 
} 
#elif defined(_WIN32) 
#include <windows.h> 

double get_performance_frequency() 
{ 
    unsigned _int64 frequency; 
    QueryPerformanceFrequency((LARGE_INTEGER*) &frequency); // just assume it works 
    return double(frequency); 
} 

double performance_frequency = get_performance_frequency(); 

double time() 
{ 
    unsigned _int64 counter; 
    QueryPerformanceCounter((LARGE_INTEGER*) &counter); 
    return double(counter)/performance_frequency; 
} 
#else 
# error time() not implemented for your platform 
#endif 

// How many times to repeat the whole test 
const int repeats = 10; 

// How many times to iterate one case 
const int times = 1000000; 

// Trick optimizer to not remove code 
int result = 0; 



// Case 1. No exception thrown nor handled. 

void do_something() 
{ 
    ++result; 
} 

void case1() 
{ 
    do_something(); 
} 



// Case 2. No exception thrown, but handler installed 

#ifndef NO_EXCEPTIONS 
void do_something_else() 
{ 
    --result; 
} 

void case2() 
{ 
    try 
    { 
     do_something(); 
    } 
    catch (int exception) 
    { 
     do_something_else(); 
    } 
} 



// Case 3. Exception thrown and caught 

void do_something_and_throw() 
{ 
    throw ++result; 
} 

void case3() 
{ 
    try 
    { 
     do_something_and_throw(); 
    } 
    catch (int exception) 
    { 
     result = exception; 
    } 
} 
#endif // !NO_EXCEPTIONS 

void (*tests[])() = 
{ 
    case1, 
#ifndef NO_EXCEPTIONS 
    case2, 
    case3 
#endif // !NO_EXCEPTIONS 
}; 

int main() 
{ 
#ifdef NO_EXCEPTIONS 
    printf("case0\n"); 
#else 
    printf("case1\tcase2\tcase3\n"); 
#endif 
    for (int repeat = 0; repeat < repeats; ++repeat) 
    { 
     for (int test = 0; test < sizeof(tests)/sizeof(tests[0]); ++test) 
     { 
      double start = time(); 

      for (int i = 0; i < times; ++i) 
       tests[test](); 

      double end = time(); 

      printf("%f\t", (end - start) * 1000000.0/times); 
     } 
     printf("\n"); 
    } 

    return result; // optimizer is happy - we produce a result 
} 
+1

Me interesarán los resultados en su plataforma ... –

+1

¿Intentó hacer una prueba en la que atraparía alguna excepción (captura (...)). Puede ser diferente a la captura de una sola clase de excepción ... –

2

No hay buena manera de meassure que en el código. Necesitarías usar un perfilador.

Esto no le mostrará directamente cuánto tiempo se dedica al manejo de excepciones, pero con un poco de investigación descubrirá cuáles de los métodos de tiempo de ejecución tratan con las excepciones (por ejemplo, para VC++ .NET es __cxx_exc [.. .]).

Agregue sus tiempos y usted tiene la sobrecarga. En nuestro proyecto, utilizamos vTunes de Intel que funciona tanto con Visual C++ como con gcc.

Editar: Bueno, si solo necesitas un número genérico que funcione. Pensé que tenías una aplicación real para crear un perfil donde no puedes simplemente desactivar las excepciones.

34

La sección 5.4 del draft Technical Report on C++ Performance está completamente dedicada a la sobrecarga de excepciones.

+3

Esto podría mejorarse al citar el contenido relevante en la respuesta, en caso de que el enlace se apague. – OMGtechy

2

Otra nota sobre el rendimiento del manejo de excepciones: las pruebas simples no tienen en cuenta el almacenamiento en caché. El código de prueba y el código de captura son tan pequeños que todo encaja en las cachés de datos e instrucciones.Pero los compiladores pueden tratar de mover el código de captura lejos del código de prueba, lo que reduce la cantidad de código que se debe mantener en la memoria caché normalmente, mejorando así el rendimiento.

Si compara el manejo de excepciones con la comprobación de valor de retorno estilo C tradicional, este efecto de almacenamiento en caché también debe tenerse en cuenta (la pregunta generalmente se ignora en las discusiones).

Carl

0

¿No será la respuesta dependerá de lo que la limpieza tiene que ocurrir como resultado de un tiro? Si se lanza un excpetion que hace que toda una carga de objetos salga del alcance de la pila, eso aumentará la sobrecarga.

En otras palabras, no estoy seguro de si hay una respuesta a la tercera pregunta que sea independiente de los detalles del código.

+0

Buen punto, y me pregunto cuántas pruebas no tienen en cuenta el tiempo dedicado a destruir esos objetos en la versión codificada sin excepciones, donde se distribuye en más rutinas. –

0

Se muestran todos los detalles sobre cómo g ++ maneja las excepciones here. Lo describe como la arquitectura Itanium, sin embargo, las técnicas generales utilizadas son las mismas. No le indicará los gastos generales exactos en términos de tiempo, sin embargo, puede determinar cuál será la sobrecarga del código aproximado.

Cuestiones relacionadas