The Cost of C++ Exceptions and setjmp/longjmp -


i wrote test measure cost of c++ exceptions threads.

#include <cstdlib> #include <iostream> #include <vector> #include <thread>  static const int n = 100000;  static void dosomething(int& n) {     --n;     throw 1; }  static void throwmanymanytimes() {     int n = n;     while (n)     {         try         {             dosomething(n);         }         catch (int n)         {             switch (n)             {             case 1:                 continue;             default:                 std::cout << "error" << std::endl;                 std::exit(exit_failure);             }         }     } }  int main(void) {     int ncpus = std::thread::hardware_concurrency();     std::vector<std::thread> threads(ncpus);     (int = 0; < ncpus; ++i)     {         threads[i] = std::thread(throwmanymanytimes);     }     (int = 0; < ncpus; ++i)     {         threads[i].join();     }     return exit_success; } 

here's c version wrote fun.

#include <stdio.h> #include <stdlib.h> #include <setjmp.h> #include <glib.h>  #define n 100000  static gprivate jumpbuffer;  static void dosomething(volatile int *pn) {     jmp_buf *pjb = g_private_get(&jumpbuffer);      --*pn;     longjmp(*pjb, 1); }  static void *throwmanymanytimes(void *p) {     jmp_buf jb;     volatile int n = n;      (void)p;     g_private_set(&jumpbuffer, &jb);     while (n)     {         switch (setjmp(jb))         {         case 0:             dosomething(&n);         case 1:             continue;         default:             printf("error\n");             exit(exit_failure);         }     }     return null; }  int main(void) {     int ncpus = g_get_num_processors();     gthread *threads[ncpus];     int i;      (i = 0; < ncpus; ++i)     {         threads[i] = g_thread_new(null, throwmanymanytimes, null);     }     (i = 0; < ncpus; ++i)     {         g_thread_join(threads[i]);     }     return exit_success; } 

the c++ version runs slow compared c version.

$ g++ -o3 -g -std=c++11 test.cpp -o cpp-test -pthread $ gcc -o3 -g -std=c89 test.c -o c-test `pkg-config glib-2.0 --cflags --libs` $ time ./cpp-test  real    0m1.089s user    0m2.345s sys     0m1.637s $ time ./c-test  real    0m0.024s user    0m0.067s sys     0m0.000s 

so ran callgrind profiler.

for cpp-test, __cxz_throw called 400,000 times self-cost of 8,000,032.

for c-test, __longjmp_chk called 400,000 times self-cost of 5,600,000.

the whole cost of cpp-test 4,048,441,756.

the whole cost of c-test 60,417,722.


i guess more saving state of jump-point , later resuming done c++ exceptions. couldn't test larger n because callgrind profiler run forever c++ test.

what cost involved in c++ exceptions making many times slower setjmp/longjmp pair @ least in example?

this design.

c++ exceptions expected exceptional in nature , optimized thusly. program compiled efficient when exception not happen.

you can verify commenting out exception tests.

in c++:

    //throw 1;  $ g++ -o3 -g -std=c++11 test.cpp -o cpp-test -pthread  $ time ./cpp-test  real    0m0.003s user    0m0.004s sys     0m0.000s 

in c:

    /*longjmp(*pjb, 1);*/  $ gcc -o3 -g -std=c89 test.c -o c-test `pkg-config glib-2.0 --cflags --libs`  $ time ./c-test  real    0m0.008s user    0m0.012s sys     0m0.004s 

what cost involved in c++ exceptions making many times slower setjmp/longjmp pair @ least in example?

g++ implements zero-cost model exceptions, have no effective overhead* when exception not thrown. machine code produced if there no try/catch block.

the cost of zero-overhead table lookup must performed on program counter when exception is thrown, determine jump appropriate code performing stack unwinding. puts entire try/catch block implementation within code performing throw.

your cost table lookup.

*some minor timing voodoo may occur, presence of pc lookup table may affect memory layout, may affect cpu cache misses.


Comments

Popular posts from this blog

qt - Using float or double for own QML classes -

Create Outlook appointment via C# .Net -

ios - Swift Array Resetting Itself -