Потенциальные исключения несут накладные расходы? - PullRequest
2 голосов
/ 02 декабря 2009

Будет ли фрагмент кода, который потенциально генерирует исключение, иметь ухудшенную производительность по сравнению с аналогичным кодом, который не возникает, когда исключение не генерируется?

Ответы [ 9 ]

4 голосов
/ 02 декабря 2009

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

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

3 голосов
/ 02 декабря 2009

Это зависит; Основанные на таблицах реализации (которые, как я считаю, используются в современном g ++ и которые являются стратегией, используемой для двоичных файлов x64 в Windows), сводят к нулю непроизводительные затраты на обработку исключений (за счет незначительного увеличения использования памяти). Обработка исключений на основе функций (которую использует Windows x86) приводит к небольшому снижению производительности даже для исключений, не вызванных выбросами.

1 голос
/ 02 декабря 2009

Поскольку компилятору нужно генерировать код, который будет перематывать стек при возникновении исключения, за кулисами добавлен некоторый дополнительный код. Но это спорно, если это значительно больше, то:

  • код, который генерируется для автоматического вызова деструкторов, когда переменные выходят из области видимости,

  • и код, который вы должны будете написать, чтобы проверить состояние завершения каждого вызова и обработать ошибку.

Что дорого, так это перехват ошибок: операторы try ... catch и что происходит, когда генерируется исключение:

  • хранение информации о каждом месте, где добавляется try ... catch (также неявно добавляется, например, вокруг деструкторов или в спецификациях исключений),

  • много стека, чтобы развернуть (и вызвать деструкторы) для чего-то, что выглядит как простой прыжок,

  • соответствующее исключение, выдаваемое в предложения catch (),

  • копирование исключений.

1 голос
/ 02 декабря 2009

Это зависит от компилятора, но ответ почти наверняка "да". В частности, если область содержит объект с нетривиальным деструктором, то этот объект должен быть зарегистрирован во время выполнения, чтобы вызвать деструктор для исключения. Например:

struct Thing
{
    ~Thing();
    void Process();
};

for (int i = 0; i < 1000000; ++i)
{
    Thing thing;
    thing.Process();
}

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

Кроме того, при входе или выходе из блоков try возникают небольшие издержки, поскольку соответствующий блок catch добавляется или удаляется из стека обработчиков исключений.

1 голос
/ 02 декабря 2009

Это зависит от вашего компилятора. Некоторые комбинации компилятор / среда выполнения выполняют дополнительную работу при входе в блок с помощью обработчиков catch. Другие строят статическую структуру данных, и вся работа происходит при броске. Стоимость входа будет ниже, чем бросок во всех случаях, но вы должны быть осторожны с блоком catch во внутренних циклах. Измерьте временные затраты с помощью интересующего вас компилятора.

1 голос
/ 02 декабря 2009

Попробуйте дешево, поймать дешево, бросить дорого. Очевидно, есть небольшая дополнительная обработка, выполняющая код, который обернут внутри попытки.

Используйте исключение для исключительных вещей - тогда накладные расходы не будут иметь значения.

0 голосов
/ 15 декабря 2010

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

0 голосов
/ 25 ноября 2010

независимо от того, «возможно ли реализовать нулевые накладные расходы при отсутствии исключений», и во всех этих теоретических дискуссиях реальность такова, что для некоторых компиляторов (g ++ 4.4) даже с оптимизацией -O2, просто факт Предложение внутри функции с зацикленной петлей (то есть cpu-bound ) сделает функцию где-то в 10-100 раз медленнее, и вот подвох: это когда бросок фактически никогда не выполняется .

Поэтому я предлагаю избегать стандартной обработки исключений в c ++, такой как чума (если вы не докажете, что я не прав); используйте boost.context, если вы хотите выполнять обработку ошибок в чувствительном к производительности приложении

0 голосов
/ 02 декабря 2009

Код Ya с обработкой исключений медленнее и также больше по сравнению с кодом без обработки исключений.

Поскольку он должен вести учет объектов, подлежащих уничтожению во время процесса разматывания стека при возникновении исключения.

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