Вопрос по performance, exception, c++ – Стоимость создания исключений C ++ 0x

13

Какое влияние на производительность выдает исключение в C ++ 0x? Насколько зависит этот компилятор? Это не то же самое, что спрашиватькакова стоимость входа вtry block, even if no exception is thrown.

Должны ли мы ожидать использования исключений больше для общей логической обработки, как в Java?

@ Bill: s / in Java / EVER / Они называются «исключениями» по причине; они исключительные. Pesto
Там будет цена за исключения. Но это не должно быть то, что вас беспокоит. Должна быть разница в стоимости между использованием исключений и получением одной и той же информации без использования исключений (поэтому необходимо возвращать код ошибки >>>> И <<<<< проверки на каждом уровне обратного вызова). Бьюсь об заклад, стоимость будет примерно такой же. Разница заключается в более чистом коде (следовательно, в ремонтопригодности). Martin York
Почему вы думаете, что исключения C ++ 0x будут сильно отличаться от других исключений? Я думаю, что большая часть вариаций будет между реализациями. David Thornley
Вы не должны использовать исключения для обработки общей логики в Java. Bill the Lizard
Не могли бы вы объяснить, как мой тест должен быть изменен, чтобы у вас была возможность выиграть эту ставку? Моя функция "thrower" просто вызывает и возвращает void. Моя функция «возврат» выполняет вызов, проверяет возвращаемое значение и соответственно возвращает успех или неудачу. Функция «метатель» явно медленнее, но не настолько медленная, чтобы беспокоить большинство приложений. Steve Jessop

Ваш Ответ

9   ответов
36
#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 уровней стека я увеличил количество повторений до 10 000, потому что все было в 10 раз быстрее. Таким образом, исключение стоит 0,1 м

Для 10 000 уровней стека это было 18,7 с против 4,1 с, поэтому около 14 мс дополнительной стоимости за исключением. Таким образом, для этого примера мы рассматриваем довольно постоянные издержки 1,5us на уровень стека (где каждый уровень разрушает один объект).

Очевидно, что C ++ 0x не определяет производительность для исключений (или чего-либо еще, кроме сложности Big-O для алгоритмов и структур данных). Я не думаю, что это изменяет исключения таким образом, что это серьезно повлияет на многие реализации, положительно или отрицательно.

Это отличный ответ, потому что тесты и интерпретация данных говорят гораздо больше, чем «я думаю, бла-бла-бла». Если бы вы могли повторить это с Windows и некоторыми версиями Visual Studio, это был бы фактический ответ на обработку исключени Edison Gustavo Muenz
Я не думаю (не каламбур), что тестирование реализации стоит того, чтобы сказать, что вы о чем-то думаете. Если ваши мысли оцениваются и основаны на фактах, то они одинаково действительны, по-другому. Этот будет фактическим ответом для «gcc и msvc, неоптимизированная сборка для x86». Но, как вы понимаете, есть гораздо больше компиляторов и намного больше конфигураций сборки :) В любом случае, +1 от меня за этот исследовательский ответ Johannes Schaub - litb
@ darth: к вашему второму вопросу, вопрос был «должны ли мы использовать исключения для общей логической обработки». Я думаю, что было бы справедливо предположить, что если кто-то это сделает (и этот тест предназначен для исследования того, что произойдет, если он это сделает), то функции вернутся только в случае успеха, а затем - в случае сбоя. Таким образом, нет ошибок коды для проверки. Я не говорю, что мне всегда нравится полученный код, но вопрос в том, как он будет работать. Кажется, ответ таков: «в этом упрощенном тесте, не так уж плохо для многих практических целей». Если у вас есть лучший тест, давайте посмотрим: -) Steve Jessop
Тестирование с Windows / VS будет недостаточно. Реализация исключений полностью отличается между win32 и win64. (А также для Windows, работающей на x86 против Itanium) jalf
У меня нет MSVC под рукой (это было запущено в Windows XP с использованием g ++ и cygwin). Я бы тоже былочен осторожно заявляя, что это хороший тест, так как вы никогда не знаете с простыми вещами, сможет ли какой-нибудь компилятор smart-alec выяснить, как оптимизировать рекурсию в том или ином случае. Если бы это произошло однажды в тесте на соответствие, который должен был проверить, что система имеет стек для N уровней рекурсии. Устанавливать структуры по ходу дела - это довольно надежный способ предотвратить это, но я не даю никаких обещаний, и результаты следует интерпретировать довольно осторожно на каждой платформе. Steve Jessop
3

что они будут иметь примерно такую же производительность, как в C ++ 03, что «очень медленно!» И нет, исключения должны использоваться в исключительных случаях из-за конструкции try-catch-throw на любом языке. Вы делаете что-то не так, если вы используете throw для управления потоком программ в Java.

@ onebyone - это не FUD с точки зрения производительности, снижение производительности является реальным и очень значительным, а исключения наносят ущерб приложениям реального времени. Not Sure
Для значений "очень медленно!" приблизительно 1 мс на моем ноутбуке и компиляторе c ++. Очевидно, что если это в вашей внутренней петле, это проблема. Я думаю, что причина не использовать исключения для ситуаций, не связанных с ошибками, состоит в том, что это затрудняет отслеживание потока управления вашего кода, а не FUD в отношении производительности. Steve Jessop
Это жульничество, если вы говорите, что стоимость исключений является «очень значительной», не зная, какой процент будет медленнее, если фактическое приложение будет работать в результате их использования. Иногда это важно, обычно это не так. И вы не можете использовать «это сломало бы приложение реального времени» в качестве причины, чтобы не использовать определенную языковую функцию, так как (а) почти все приложения не работают в реальном времени, и (б) почти все языковые функции могут сломать приложение реального времени, делая невозможным прогнозирование ошибок кэша и тому подобное. Steve Jessop
10


Что такое цена исключения не является полезной, более полезной является стоимость исключений относительно альтернативы. Таким образом, вам нужно измерить, сколько стоят исключения, и сравнить их с возвращением кодов ошибок >>> И <<< проверки кодов ошибок на каждом уровне стека раскручивать.

Также обратите внимание, что использование исключений не должно быть сделано, когда вы контролируете все. Внутри класса возвращение кода ошибки, вероятно, является лучшей техникой. Исключения следует использовать для передачи управления во время выполнения, когда вы не можете определить, как (или в каком контексте) ваш объект будет использоваться во время выполнения.

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

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

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

Ответ, как всегда, зависит (сделайте профиль и используйте быстрый, если это то, что вам нужно).

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

"Теперь рассмотрим дополнительный код, который вам нужно написать, чтобы передать код ошибки". Мой тестовый пример пытается смоделировать это (см. Рекурсивный вызов функции "returner"). Я не проверял, оптимизирует ли это компилятор. Так что моя оценка 13us для исключения, перехваченного на 3 уровня, может быть завышенной. Мой цикл throw определенно намного медленнее, чем цикл return error. Конечно, это еще до того, как будет добавлена любая реальная работа. Буду признателен за любые предложения о том, как сделать так, чтобы мой цикл «возврат» более точно отражал обработку ошибок «проверьте код возврата и выручите». Steve Jessop
В частности, «возвращающий» может быть медленнее в Успех case, в зависимости от того, каким образом компилятор выбрал создание ветви. Вы часто не очень много слышите о «исключениях! Тьфу! толпа о том, как они вводят дополнительные ветви (по сравнению с обработкой ошибок на основе исключений) в случае нормальной, успешной работы. Steve Jessop
6

по которым исключения в C ++ 0x должны быть быстрее или медленнее, чем в C ++ 03. А это значит, что их производительность полностью зависит от реализации. Windows использует совершенно разные структуры данных для реализации обработки исключений в 32-разрядной и 64-разрядной версиях, а также в Itanium и x86. Linux не гарантированно придерживается одной и только одной реализации. Это зависит. Существует несколько популярных способов реализации обработки исключений, и все они имеют свои преимущества и недостатки.

Так что это зависит не от языка (c ++ 03 против 0x), а от компилятора, библиотеки времени выполнения, архитектуры ОС и процессора.

14

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

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

+ 1 для использования исключений только для исключительных условий Alex B
+ 1 от меня тоже. Использование исключений для нормальной логики может привести к «спагетти-исключениям», где работа - полтора, чтобы просто выяснить, где вещь поймана. Особенно с полиморфным кодом, когда вы можете даже не знать, какая реализация ListenerRegistry является вашим вызывающим абонентом, если не считать его запуска и просмотра того, какую трассировку стека вы получаете в текущей конфигурации. Если исключения используются только для ситуаций, которые, как ожидается, будут невосстановимыми, то большинство уровней кода даже не будут думать о попытках восстановления после них: -) Steve Jessop
8

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

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, функции исключений стали двумя из 5 лучших пользователей процессорного времени.

Это для меня дорого

ouch. это большое влияние. sean riley
Помните, что для каждого кадра стека вы должны вызывать все деструкторы локальных объектов и уничтожать локальную память. Каждый кадр будет занимать немалое количество памяти. Вот почему они должны быть зарезервированы для «исключительных» условий. Chris K
Да, это действительно так. Когда я его профилировал, я выполнял очень простой код, который никогда не выдавал исключение (кроме как в конце), но пытался поймать, все еще требуя, чтобы стек был размотан. И, что касается clafiy, я имею в виду две функции исключения (есть две с gcc), одна из пяти перечисленных функций, отсортированных по количеству потребляемого процессорного времени Earlz
4

что C ++ 0x добавляет или изменяет что-либо в работе исключений C ++. Для общего совета посмотримВо.

0

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

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

EDIT: И так как это получило отрицательный ответ (плюс повышенный голос, так что +8 для меня!), Я поясню вышеизложенное с меньшим количеством юмора и большей информацией: исключение, по крайней мере в земле C ++, требует RTTI и компилятор и, возможно, работает Система магии, которая превращает в их исполнение гигантскую черную дыру неопределенности. (Вам даже не гарантируется, что они сработают, но такие случаи происходят во время других более серьезных событий, таких как нехватка памяти или просто уничтожение пользователем процесса или фактически загорающаяся машина.) Так что, если вы используете их, то это должно быть потому, что вы хотите изящно восстановиться из ситуации, которая в противном случае могла бы вызвать что-то ужасное, но у этого восстановления не может быть никаких ожиданий на быстродействие (каким бы оно ни было для вашего конкретного приложения).

Так что, если вы собираетесь использовать исключения, вы ничего не можете сказать о влиянии на производительность.

Какая? Исключения не требуют магии операционной системы и магии компилятора. Они хорошо поняты. Не гарантировано уволить? Извините, но это совершенно неправильно. Исключения могут быть чрезвычайно полезны для управления ошибками и непредвиденными условиями, а также для создания более обслуживаемого кода путем разделения нормальных путей и путей ошибок. Вы просто не можете сказать, что они почти никогда не стоят затрат. Не всем приложениям требуется высокая производительность или производительность в реальном времени, и часто вам не важна производительность, когда ваша программа находится в состоянии ошибки. Brian Neal
Попытка понизить голосование из-за бессмыслицы о «не гарантированно для стрельбы», но остальная часть вашего поста имеет смысл (вы ничего не можете предположить о производительности исключений), поэтому я не буду. Правда, технически не гарантируется, что исключение сработает, но и функция не будет гарантированно оценена при его вызове. Там тоже может не хватить места в стеке. Пользователь может выключить компьютер. Сказать, что они не гарантированы, вводит в заблуждение до крайности. jalf
Смотря на количество сбоев страниц в секунду на моем компьютере, я очень переживаю, что кто-нибудь когда-нибудь может объединить ответ earlz («прерывания, эмулируемые с исключениями») и ваш («исключения запускают пользователя в голову»). Steve Jessop
Системы, которые должны быть устойчивыми при сбое, могут использовать поля стека и т. Д., Если они также хотят использовать исключения. То же самое, что обработчики прерываний (часто) запускаются в отдельном стеке, так что они все еще работают в критических ситуациях, когда не хватает ресурсов. Steve Jessop
Конечно, если случается больше плохих вещей, когда исключение уже активно, оно может не «сработать». Но в этот момент игра окончена, и ваша программа все равно может вылететь. То есть ничего не сработает. Это не причина избегать исключений. Brian Neal
-1

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

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

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

Вы понимаете, что если вы вернетесь нормально, стек все равно придется разматывать? Steve Jessop
Исключения в основном бесплатны, в то время как нет исключений, объясняющих дополнительные затраты на размещение блоков try catch, в лучшем случае ничтожных. Разматывание из-за исключительной ситуации обходится дороже, но не дороже, чем писать код для возврата кодов ошибок. Таким образом, утверждение, что это дорого, полностью ложно. Martin York

Похожие вопросы