Стоимость броска исключений С++ 0x
Каковы последствия производительности для исключения исключений в С++ 0x? Сколько стоит этот компилятор? Это не то же самое, что запрашивать что такое стоимость ввода блока try
, даже если исключение не выбрано.
Должны ли мы ожидать использования исключений больше для обработки общей логики, например, в Java?
Ответы
Ответ 1
#include <iostream>
#include <stdexcept>
struct SpaceWaster {
SpaceWaster(int l, SpaceWaster *p) : level(l), prev(p) {}
// we want the destructor to do something
~SpaceWaster() { prev = 0; }
bool checkLevel() { return level == 0; }
int level;
SpaceWaster *prev;
};
void thrower(SpaceWaster *current) {
if (current->checkLevel()) throw std::logic_error("some error message goes here\n");
SpaceWaster next(current->level - 1, current);
// typical exception-using code doesn't need error return values
thrower(&next);
return;
}
int returner(SpaceWaster *current) {
if (current->checkLevel()) return -1;
SpaceWaster next(current->level - 1, current);
// typical exception-free code requires that return values be handled
if (returner(&next) == -1) return -1;
return 0;
}
int main() {
const int repeats = 1001;
int returns = 0;
SpaceWaster first(1000, 0);
for (int i = 0; i < repeats; ++i) {
#ifdef THROW
try {
thrower(&first);
} catch (std::exception &e) {
++returns;
}
#else
returner(&first);
++returns;
#endif
}
#ifdef THROW
std::cout << returns << " exceptions\n";
#else
std::cout << returns << " returns\n";
#endif
}
Результаты сравнения Mickey Mouse:
$ make throw -B && time ./throw
g++ throw.cpp -o throw
1001 returns
real 0m0.547s
user 0m0.421s
sys 0m0.046s
$ make throw CPPFLAGS=-DTHROW -B && time ./throw
g++ -DTHROW throw.cpp -o throw
1001 exceptions
real 0m2.047s
user 0m1.905s
sys 0m0.030s
Таким образом, в этом случае бросание исключения на 1000 уровней стека, а не возврат нормально, занимает около 1,5 мс. Это включает ввод блока try, который, как я считаю, в некоторых системах свободен во время выполнения, а другие берут на себя затраты каждый раз, когда вы вводите try, а на других - только каждый раз, когда вы вводите функцию, содержащую попытку. Для более 100 уровней стека я увеличил повторы до 10k, потому что все было в 10 раз быстрее. Таким образом, исключение составляет 0,1 мс.
Для 10 000 уровней стека это было 18.7s против 4.1s, поэтому около 14ms дополнительных затрат для исключения. Итак, для этого примера мы смотрим на довольно непростые накладные расходы на 1,5% на уровень стека (где каждый уровень разрушает один объект).
Очевидно, что С++ 0x не определяет производительность для исключений (или что-то еще, отличное от сложности большого-O для алгоритмов и структур данных). Я не думаю, что это изменяет исключения таким образом, который серьезно повлияет на многие реализации, как положительно, так и отрицательно.
Ответ 2
Производительность исключений очень зависит от компилятора. Вам нужно будет профилировать ваше приложение, чтобы узнать, не является ли оно проблемой. В общем, этого не должно быть.
Вы действительно должны использовать исключения для "исключительных условий", а не для обработки общей логики. Исключения идеальны для разделения нормальных путей через коды кода и ошибок.
Ответ 3
Я в основном думаю, что был задан неправильный вопрос.
Какая стоимость исключения не является полезной, более полезной является стоимость исключений по сравнению с альтернативой. Таким образом, вам нужно измерить, сколько исключений стоит и сравнивается с тем, чтобы возвращать коды ошибок → > И < < проверяя коды ошибок на каждом уровне стека.
Также обратите внимание, что использование исключений не должно выполняться, когда вы контролируете все. В классе, возвращающем код ошибки, вероятно, лучший метод. Исключения должны использоваться для передачи контроля во время выполнения, когда вы не можете определить, как (или в каком контексте) ваш объект будет использоваться во время выполнения.
В основном он должен использоваться для переноса управления на более высокий уровень контекста, где объект с достаточным контекстом поймет, как справиться с исключительной ситуацией.
Учитывая этот принцип использования, мы видим, что исключения будут использоваться для передачи управления несколькими уровнями в стеке кадров. Теперь рассмотрим дополнительный код, который вам нужно написать, чтобы передать код ошибки, резервное копирование того же стека вызовов. Рассмотрим дополнительную сложность, добавляемую тогда, когда коды ошибок могут поступать из нескольких разных направлений и пытаться подключить все типы кода ошибки.
Учитывая это, вы можете увидеть, как исключения могут значительно упростить поток кода, и вы можете увидеть сложность улучшения потока кода. Тогда вопрос становится исключением погодных условий, более дорогостоящих, чем сложные тесты условий ошибок, которые должны выполняться в каждом кадре стека.
Ответ как всегда зависит (сделайте оба профиля и используйте quickist, если это то, что вам нужно).
Но если скорость не единственная стоимость.
Поддержание работоспособности - это стоимость, которую можно измерить. Используя эту метрику стоимости Исключения всегда выигрывают, так как они в конечном итоге делают поток конструирования кода просто задачей, которую нужно выполнить, а не задачей и контролем ошибок.
Ответ 4
Я однажды создал библиотеку эмуляции x86 и использовал исключения для прерываний и т.д. Плохая идея. Даже когда я не выбрасывал никаких исключений, это сильно влияло на мою основную петлю. Что-то вроде этого было моей основной петлей
try{
CheckInterrupts();
*(uint32_t*)&op_cache=ReadDword(cCS,eip);
(this->*Opcodes[op_cache[0]])();
//operate on the this class with the opcode functions in this class
eip=(uint16_t)eip+1;
}
//eventually, handle these and do CpuInts...
catch(CpuInt_excp err){
err.code&=0x00FF;
switch(err.code){
Накладные расходы, связанные с тем, что этот код в блоке try сделали исключение, используют 2 из 5 лучших пользователей времени процессора.
Что, мне дорого
Ответ 5
Нет причин, по которым исключения в С++ 0x должны быть более быстрыми или медленными, чем в С++ 03. А это означает, что их производительность полностью зависит от реализации. Windows использует совершенно разные структуры данных для реализации обработки исключений для 32-разрядных и 64-разрядных версий, а также для Itanium vs x86. Linux не гарантированно придерживается одной и только одной реализации. Это зависит. Существует несколько популярных способов реализации обработки исключений, и все они имеют преимущества и недостатки.
Таким образом, это не зависит от языка (С++ 03 vs 0x), а от компилятора, библиотеки времени выполнения, архитектуры ОС и ЦП.
Ответ 6
Я не думаю, что С++ 0x добавляет или изменяет что-либо в том, как работают исключения С++. Для общей рекомендации посмотрите здесь.
Ответ 7
Казалось бы, у них будет такая же производительность, как в С++ 03, которая "очень медленная!" И нет, исключения должны использоваться в исключительных обстоятельствах из-за конструкции try-catch-throw на любом языке. Вы делаете что-то неправильно, если вы используете throw для управления потоком программ в java.
Ответ 8
Представьте, что звонок погаснет, компьютер перестает принимать любой ввод в течение трех секунд, а затем кто-то ударяет пользователя по голове.
Это стоимость исключения. Если это предотвратит потерю данных или машину от поджога, это стоит того. В противном случае, вероятно, это не так.
EDIT: И так как это получило downvote (плюс upvote, так что +8 для меня!), я разъясню выше с меньшим количеством юмора и дополнительной информации: исключение, по крайней мере на С++, требует RTTI и компилятора и возможно, магии операционной системы, что делает их производительность гигантской черной дырой неопределенности. (Вам даже не гарантировано, что они будут срабатывать, но эти случаи случаются во время других более серьезных событий, таких как нехватка памяти, или пользователь просто убивает процесс или машину, на самом деле ловущую огонь.) Поэтому, если вы их используете, это должно быть из-за того, что вы хотите изящно оправиться от ситуации, которая в противном случае могла бы вызвать что-то ужасное, но это восстановление не может иметь никаких ожиданий выполнения работы (что бы это ни было для вашего конкретного приложения).
Итак, если вы собираетесь использовать исключения, вы не можете ничего принимать о последствиях производительности.
Ответ 9
Обработка исключений - дорогостоящая функция, в общем, потому что бросание/захват подразумевает дополнительный код, который должен быть выполнен, чтобы обеспечить проверку состояния разворота и отслеживания стека.
Насколько я понял из некоторых чтений, для Visual С++, например, есть некоторые довольно сложные структуры и логика, встроенные в код для обеспечения этого. Поскольку большинство функций могут вызывать другие функции, которые могут генерировать исключения, некоторые издержки для разматывания стека могут существовать даже в этих случаях.
Однако, прежде чем думать об избыточных накладных расходах, лучше измерить влияние использования исключений в вашем коде перед любым действием оптимизации. Избежание излишней обработки исключений должно препятствовать обработке исключений значительных накладных расходов.