Измерение издержек обработки исключений в C ++ - PullRequest
15 голосов
/ 04 сентября 2008

Каков наилучший способ измерить издержки при обработке исключений / производительность в C ++?

Пожалуйста, дайте автономные образцы кода.

Я использую Microsoft Visual C ++ 2008 и gcc.

Мне нужно получить результаты в следующих случаях:

  1. Накладные расходы, когда нет блоков try / catch
  2. Накладные расходы, когда есть блоки try / catch, но исключения не генерируются
  3. Накладные расходы при возникновении исключений

Ответы [ 8 ]

34 голосов
/ 04 сентября 2008

Раздел 5.4 проекта технического отчета о производительности C ++ полностью посвящен накладным расходам на исключения.

9 голосов
/ 04 сентября 2008

В качестве предложения: не слишком беспокоиться о накладных расходах, когда создаются исключения Реализации обработки исключений обычно делают не быстрое бросание и медленную ловлю. Это нормально, так как эти случаи, ну, в общем, исключительные.

Карл

8 голосов
/ 04 сентября 2008

Вот код измерения, который я придумал. Видите ли вы какие-либо проблемы с этим?

Пока работает в Linux и Windows, скомпилируйте с:

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

или, например, Visual C ++ Express .

Чтобы получить базовый вариант («поддержка исключений полностью исключена из языка»), используйте:

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

или аналогичные настройки в MSVC.

Некоторые предварительные результаты здесь . Они, вероятно, все ненормальные из-за разной загрузки машины, но они дают некоторое представление об относительных издержках обработки исключений. (Краткое содержание: нет или мало, когда не генерируются исключения, огромно, когда они действительно генерируются.)

#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
}
3 голосов
/ 05 сентября 2008

Кевин Фрей говорит о стоимости производительности обработки исключений в своей речи " Стоимость обработки исключений в C ++ в Windows ". (В разделе «Сводка и выводы» есть один элемент списка, который гласит: «[Стоимость выполнения обработки исключений] не всегда поддается измерению».)

2 голосов
/ 04 сентября 2008

Еще одно замечание о производительности обработки исключений: простые тесты не учитывают кэширование. Try-код и catch-код настолько малы, что все помещается в кэш инструкций и данных. Но компиляторы могут попытаться переместить код перехвата подальше от кода попытки, что уменьшает объем кода, который обычно сохраняется в кэше, что повышает производительность.

Если вы сравниваете обработку исключений с традиционной проверкой возвращаемого значения в стиле C, этот эффект кэширования также следует учитывать (вопрос обычно игнорируется в обсуждениях).

Карл

2 голосов
/ 04 сентября 2008

Нет действительно хорошего способа измерить это в коде. Вам необходимо использовать профилировщик.

Это не будет показывать вам напрямую, сколько времени тратится на обработку исключений, но, проведя небольшое исследование, вы узнаете, какие из методов выполнения работают с исключениями (например, для VC ++. NET это __cxx_exc [... ]).

Добавьте их время, и у вас есть накладные расходы. В нашем проекте мы использовали vTunes от Intel, которая работает как с Visual C ++, так и с gcc.

Редактировать: Хорошо, если вам просто нужен общий номер, который может работать. Думаю, у вас есть реальное приложение к профилю, где вы не можете просто отключить исключения.

0 голосов
/ 17 февраля 2009

Полная информация о том, как g ++ обрабатывает исключения, показана здесь . Это описывает это как для архитектуры Itanium, однако общие используемые методы - то же самое. Это не скажет вам точных затрат времени, однако вы можете понять, какой будет грубый код.

0 голосов
/ 05 сентября 2008

Разве ответ не будет зависеть от того, какая очистка должна произойти в результате броска? Если генерируется исключение, которое приводит к тому, что вся нагрузка объектов выходит за пределы области видимости вверх по стеку, это увеличивает накладные расходы.

Другими словами, я не уверен, есть ли ответ на 3-й вопрос, который не зависит от особенностей кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...