Measuring exception handling overhead in C++

后端 未结 8 625
耶瑟儿~
耶瑟儿~ 2020-12-03 01:42

What is the best way to measure exception handling overhead/performance in C++?

Please give standalone code samples.

I\'m targeting Microsoft Visual C++ 2008

8条回答
  •  忘掉有多难
    2020-12-03 02:27

    Here's the measuring code I came up with. Do you see any problems with it?

    Works on Linux and Windows so far, compile with:

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

    or for example Visual C++ Express.

    To get the base case ("exception support removed from the language altogether"), use:

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

    or similar settings in MSVC.

    Some preliminary results here. They are probably all hokey because of varying machine load, but they do give some idea about the relative exception handling overhead. (Executive summary: none or little when no exceptions are thrown, huge when they actually are thrown.)

    #include 
    
    // Timer code
    
    #if defined(__linux__)
    #include 
    #include 
    
    double time()
    {
        timeval tv;
        gettimeofday(&tv, 0);
        return 1.0 * tv.tv_sec + 0.000001 * tv.tv_usec;
    }
    #elif defined(_WIN32)
    #include 
    
    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
    }
    

提交回复
热议问题