Как стать автором
Обновить

Комментарии 18

круто
а для Java подобное тестирование планируется?
То есть ответом на вопрос заголовка статьи является «не использовать исключения»? Здорово!

Ну использовать исключения не в исключительных случаях так себе идея.

Ну еще недавно появилось предложение со static exceptions от Herb Sutter, по идее это тот же expected, но на уровне языка и с почти той же идеологией исключений, что и раньше.
я правильно понимаю, что вы в 50% случаев выкидывали исключение в практически пустой функции и потом утверждали, что это долго?
а что-нибудь более реальное — типа исключение — это действительно в исключительной ситуации, объектов десяток нетривиальных создать/разрушить, ошибка в функции 3-4 уровней вложенности, а реакция выше. ну где-то так?

а потом сравнить быстродействие и объем кода, бойлер-плейта и мест для ошибки для разных вариантов.

а, пардон, это перевод. ну не самая удачная статья для перевода выбрана кмк

У вас реально может быть 50% ошибок, например, при парсинге данных снаружи. Конечно, когда процент ошибок становится выше определенного порога, то начинают костылить в стиле bool TryDoStuff, где через аут параметры возвращаются реальные данные, а булкой показывают, удачно ли прошла операция и можно ли пользоваться возвращаемым значением.


Только вот во-первых аут параметры это очень фигово (композятся они так себе, это точно), а во-вторых можно легко использовать мусорное значение, не проверив успешность операции.


С подобным expected вероятность подобного исхода ниже, а с полноценными АДТ — нулевая.

Если заменить настоящие исключения на возврат объекта ошибки, то это будет быстрее работать — да. Только это уже не будет исключениями :)
Они на то и исключения, чтобы не возникать часто — насколько оправдано вообще с этим заморачиваться в плане штатной работы приложения?

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

Исключения — для исключительных ситуаций. Если вероятность ошибки 50%, то это не исключительная ситуация, и там лучше использовать std::optional или этот expected и так далее, вариантов много. Но если вероятность ошибки 0.0001%, зато она может произойти где угодно, например, при попытке аллокации памяти через любой new, то захламлять код паттерн матчингом или анврапами тоже как-то глупо, лучше поставить где-то в самом верху один-единственный catch, который все поймает, запишет или куда-то отправит, и завершит программу. Одно другого не исключает.

Согласен

Автор оригинала не прав совсем. Скорость зависит от процентного соотношения ошибок и правильного кода, и при малом проценте ошибок исключения быстрее.
Теперь придется вам перевести еще и это https://nibblestew.blogspot.com/2017/01/measuring-execution-performance-of-c.html. Тут более подробнее правда уже на старых компиляторах.

Исключение нужно для исключительной ситуации. ИМХО исключительные ситуации имеет смысл оптимизировать тогда, когда оптимизированы все штатные.
Судя по всему, предложенное решение сочетает в себе минусы и от retval в стиле Си, и от плюсовых исключений: и (сравнительно) медленное, и может легко быть проигнорировано. Опять же, если исключение должно лететь уровней на пять вверх, весь код там превратится в лапшу из if'ов и переупаковывания Expected'ов.

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

В конце концов все изобретают очередной вариант на тему Either.

Статья демонстрирует, что если исключения не ловить, а возвращать как коды ошибок — то они сравнимы со скоростью кодов ошибок. Не очень полезное знание. И конечно потеря RAII, разматывания стека и всех тех преимуществ исключений, которые в статье обозначены.

Каким образом теряется RAII или раскрутка стека? Если раскрутка как-то и страдает из-за использования map и then, то деструкторы не перестают вызываться. Гарантии те же и даже больше, потому что больше никто не может вклиниться в неудобные места вроде вычисления аргументов функций. Писать expected safe код проще, чем exception safe.

Автор оригинала совсем не прав, ибо сравнил теплое с мягким и сделал вывод что одно кислее другого. Еще и Александреску приплел.


  1. Скорость вброса-обработки исключений не влияет на производительность, так как в нормальном коде исключения очень редки.
  2. Рецепт Александреску не про производительность, а для возврата и обработки ошибок в Go-стиле, что во многих случаях проще-удобнее по ряду причин.
  3. Предлагаемый "возврат исключений" быстрее только в случае возврата псевдо-исключений с тривиальной структурой (код ошибки), что и демонстрируют результаты (замедление в ~5 раз для normal-path).

Если не округлять углы, то в статье примерно пурга, которая только путает "джунов".

Что же вы все так набросились на статью! Да, не идеал, ради рекламы Expected много написано, но озвучить эту сторону тоже надо было.
Не надо забывать, что исключения совсем не zero cost даже, когда не бросаются, иначе бы noexcept в стандарт не тащили. Кроме затрат непосредственно на секцию try, которая в реализации SJLJ может быть очень недешёвой, есть ещё и косвенные на сломанные оптимизации. Сейчас с ходу не найду доклад, но точно был про внутренности llvm, где демонстрировалось, какие именно оптимизации ломаются.
Кроме того есть ещё разбухание бинаря (привет dwarf), -fno-exceptions и прочие интересные случаи.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий