LINUX.ORG.RU

Какой нынче перформанс в Джаве по киданию экспешенов на сервер-сайде?

 ,


0

3

Вот скажем пилим мы сервер-сайд, куча эксепшенов - все дела. Если то же число не распарсилось или поле с формы в паттерн не зашло. Казалось бы красота, перехватываем ошибки в другом слое.

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

Так-то ерунда, но мой перфекционизм, дурной голове покоя не даёт )

★★★

На одной из конференций (хоть и по мобильной разработке) Fernando Cejas ляпнул «Prefer code readability over performance» и я с ним согласен. Железа докинуть можно всегда, а исправить в будущем хреново сделанную архитектуру из-за экономии на спичках... Скорее всего это никто уже править не будет, а будут лишь подпирать костылями с обеих сторон. ИМХО.

Jefail ★★★ ()

Не вижу смысла использовать Throwable/Exception там, где можно использовать Either, или на худой конец scala.util.Try/Success/Failure. Исключения нужны там, где нужен stacktrace - если от него заранее понятно, что толку никакого - вполне норм в качестве ошибки возвращать Left, в качестве результата Right.

BattleCoder ★★★★★ ()

спекулятивный jit очевидные места разрулит(из описанного в ОП)

а в более сложных случаях, один хрен, что на каждом уровне ставить проверку if err? return err, что выбрасывать исключения

anonymous ()
Ответ на: комментарий от BattleCoder

Exception'ы должны быть инверсией управления. Вот делаешь ты запрос в базу, у тебя есть несколько вариантов факапа. EntityNotFoundException, IOException, например. И это должны быть именно исключения, тот-же спринг на них завязывается и позволяет при этом роллбэкать транзакции. А что делать в твоем подходе - не понятно.

Jefail ★★★ ()

а как именно ты собрался их использовать?

если абузить мехнизм, и каким-нибудь автогенератором оборачивать совершенно каждую строчку в try-catch - будет очень медленно

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

если беспокоишься о какой-то критичной части к0ода, засунь ее в микробенчмарк (в качестве фреймворка для микробенчмарков - JMH) и посмотри, что происходит

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

stevejobs ★★★☆☆ ()
Ответ на: комментарий от BattleCoder

Последние джавы можно сказать склоняют использовать вот такие конструкции: getValue().orElseThrow(() -> new CustomException(...))

scala.util.Try/Success/Failure

Мы простые работяги, куда нам до вас - аристократов )

foror ★★★ ()

имхо, общая идея в том, что разный код имеет разные типы критичности. В обычном веб-приложении перфоманс-критичного кода - ну дай бох 5%. В свете этого, изначальный вопрос не совсем корректный: в некритичном коде все равно что использовать; в критичном - ты и сам понимаешь, что экзепшены использовать не нужно (неважно - просадят они в 10 раз производительность, или в 110).

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

stevejobs ★★★☆☆ ()
Ответ на: комментарий от Jefail

Ну вот IOException вполне себе такое исключение, для которого особый обработчик вряд ли потребуется. А вот EntityNotFound вовсе и не исключение на самом деле, как по мне - плохой дизайн. Результат запроса может быть либо пустой, либо не пустой, пустой ответ - всё равно ответ, это не исключительная ситуация, просто такое состояние надо обрабатывать, Either/Option сюда хорошо по смыслу подходит.

BattleCoder ★★★★★ ()

Общая рекомендация: не злоупотреблять и не беспокоиться пока в них не упрешься. Вряд ли обработку ошибок придется оптимизировать в первую очередь.

ya-betmen ★★★★★ ()
Последнее исправление: ya-betmen (всего исправлений: 1)

Эксепшены на то и эксепшены, что их нужно кидать, когда что-то случилось. А если что-то случилось, клиент всё равно получит фигу, так что пофиг.

no-such-file ★★★★★ ()

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

Если есть возможность проверить что-либо банальным if, то этот способ стоит предпочесть исключению.

hippi90 ★★★★ ()
Ответ на: комментарий от Jefail

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

Во-вторых, как правило, это приводит к улучшению читаемости кода.

В-третьих, это субъективно, конечно, но многие разработчики уровня джуна-мидла не умеют нормально писать код с эксепшенами, в результате получается что-то типа такого:

//Пример синтетический
String line = null;
try {
	BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("path/to/file")));
	line = br.readLine();
} catch (Exception e) {
	e.printStackTrace();
}

hippi90 ★★★★ ()
Ответ на: комментарий от ritsufag

Зачем кидать исключение там где оно не нужно? Вижу порой люди кидают их даже при банальной валидации.

А я о чём? В ржавом вот нормально сделали. А в джаве такая вот философия эксепшенов сложилась. Сижу и думаю, а сколько это всё в итоге стоит сервер-сайду? Или может в джаве умудрились сделать эксепшены бесплатными - кидай - не хочу?

foror ★★★ ()
Ответ на: комментарий от foror

А что там в roost?
Да и в жаве никто не заставляет кидать исключения. Обычно просто возвращают объект со статусом и прочей информацией(хотя тут я не в курсе как у жавистов принято).

ritsufag ★★★★★ ()
Ответ на: комментарий от ritsufag

А что там в roost?

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

foror ★★★ ()
Ответ на: комментарий от ritsufag

Зачем кидать исключение там где оно не нужно? Вижу порой люди кидают их даже при банальной валидации.

так java после прогрева быстрее ассемблера в 7 раз, а исключения всего в 5 раз. почему бы и не использовать скорость jvm для потока управления? догматики, блин, лишь бы написать что догму используете

anonymous ()
Ответ на: комментарий от hippi90

Раскрутка стека - дорогое удовольствие.

Тогда и выход из функции - такое же дорогое удовольствие. Перестаньте уже повторять бессмысленные мантры.

asaw ★★★★★ ()
Ответ на: комментарий от hippi90

Чушь тут несешь именно ты. Иди по ссылкам, которые тебе здесь vertexua запостил. И матчасть учи. Если бы ты имел хоть какое-то представление о матчасти, то не стал бы лезть в бутылку таким школьным образом.

asaw ★★★★★ ()
Ответ на: комментарий от asaw

Раскрутка стека - дорогое удовольствие.

Тогда и выход из функции - такое же дорогое удовольствие.

Твои слова? Твои. Еще раз, давай пруф, что раскрутка стека - это так же дешево, как и возврат из функции.

Иди по ссылкам, которые тебе здесь vertexua запостил.

Сам бы сходил, Шипилёв черным по белому пишет, что раскрутка стека - дорого.

hippi90 ★★★★ ()
Ответ на: комментарий от hippi90

В таком случае иди учи английский.

Stack unwinding costs depend on how lucky we are with bringing the exception handler closer in the compiled code.

Should we eliminate both effects, the performance cost of exceptions is that of local branch.

asaw ★★★★★ ()
Ответ на: комментарий от no-such-file

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

anonymous ()

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

Почему-то вот скажем, nginx, не на жабе написан, можно подумать в этом направлении

Harald ★★★★★ ()
Ответ на: комментарий от hippi90

Сходи еще раз перечитай, это достигается при условии отключения раскрутки стека.

Это достигается при условии, если бинарный КОД ОБРАБОТЧИКА окажется рядом, а не «при условии отключения раскрутки стека», писатель.

asaw ★★★★★ ()
Ответ на: комментарий от asaw

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

vertexua ★★★☆☆ ()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от vertexua

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

ЗЫ из дальнейшего анализа этой темы становится понятна и некоторая нелепость предложения возврата пары <Результат, Ошибка> в том случае, когда ошибка - один из ожидаемых вероятных результатов (то есть когда они примерно равновероятны).

asaw ★★★★★ ()
Ответ на: комментарий от asaw

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

С другой стороны там, где это хороший тон - Scala, Go, Rust, C++ в Google, там не будет разброда и шатаний. И будет небольщой профит в аггрерированой производительности (опять же, сомнительного масштаба). В основном <Результат, Ошибка> еще выбирают за легкость определения точек выхода из функций при чтении кода. С другой стороны функции должны быть достаточно длинными и запутаными, что уже проблема в себе, чтобы это реально помогало

vertexua ★★★☆☆ ()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от asaw

Перечитай еще раз пункт 3 по ссылке. Если раскрутка стека - это дешево, то зачем отключать? Нахождение обработчика рядом с кодом, создавшим исключение, это только одно из условий, а второе - как раз отключение раскрутки стека.

По ссылке же есть и цифры:

BasicBench.dynamicException                     avgt        25     1901.196       14.572  ns/op
BasicBench.dynamicException_NoStack             avgt        25       67.029        0.212  ns/op
Выброс исключения с отключенной раскруткой стека требует в 70 раз меньше времени.

hippi90 ★★★★ ()
Ответ на: комментарий от vertexua

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

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

asaw ★★★★★ ()
Ответ на: комментарий от asaw

то обрабатывать её как в Расте не эффективно

Программисту или процессору? Процессору как раз норм. Программисту - зависит от ЯП. Вон в Rust добавил "?" в конец строки и все

vertexua ★★★☆☆ ()
Последнее исправление: vertexua (всего исправлений: 2)
Ответ на: комментарий от vertexua

Как же процессору норм, когда его драгоценный кэш засран кучей кода, который в 999 случаях из 1000 не нужен?

exception actually works better than flags for up to roughly 10-3 frequency in the default mode. The reason is that the non-exceptional path enjoys no additional overheads of checking the exceptions, since the exception handling code is laid out and handled elsewhere.

asaw ★★★★★ ()
Последнее исправление: asaw (всего исправлений: 1)
Ответ на: комментарий от asaw

Дейсвительно, в success path проверок не будет. Примеры

C++

Rust

Но первый код действительно вызывает какае-то другие вызовы в случае броска exception (которые не факт что не дойдут до конца стека). Интересно для нативных языков бы тоже узнать соотношение стоимости от вероятности exception.

vertexua ★★★☆☆ ()
Ответ на: комментарий от BattleCoder

Исключения нужны там, где нужен stacktrace

Не соглашусь. С помощью исключений можно запрограммировать «хороший» путь программы не засоряя его всякими обработками ошибок (для этого на самом верхнем уровне будет один try/catch). Полученную программу будет легче поддержитвать, чем программу с пробросом ошибок через все слои с помощью ifelse/match (это из моего личного опыта работы, возможно у кого-то судьба сложилась лучше)

dsxl ()
Ответ на: комментарий от stevejobs

Ну использовали бы его побольше, было бы неплохо. И еще должен ему в помощь быть какой-то Result<T,E> или Either<L,R>, но нету пока. Я думаю что Java с exceptionами надолго, не знаю плохо это или хорошо, но это факт

Вот класс

https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html

Методов pop() например с Optional что-то я там не вижу

vertexua ★★★☆☆ ()
Последнее исправление: vertexua (всего исправлений: 2)