Производительность Java try/catch, рекомендуется ли сохранить то, что находится внутри предложения try, до минимума?

Учитывая, что у вас есть такой код:

doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing the same kind of exceptions.

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

Мой вопрос: рекомендуется ли поддерживать строки внутри try catch до минимума?, то есть ТОЛЬКО внутри предложения try использовать строки, которые могут реально генерировать исключение, которое вы ловите. Кодирует ли код внутри предложения try медленнее или вызывает любую производительность?

Но более важно то, что это лучшее/более читаемое решение, рассматривающее это:

try {
    doSomething() // this method may throw a checked a exception
//do some assignements calculations
doAnotherThing() //this method may also throw the same type of checked exception
//more calls to methods and calculations, all throwing the same kind of exceptions.
}
catch (MyCheckedException e) {
   //handle it
}

или:

try {
    doSomething() // this method may throw a checked a exception
}
catch (MyCheckedException e) {
   //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
   continue;     
} 
 //do some assignements calculations
try {
    doAnotherThing() // this method may throw a checked a exception
}
catch (MyCheckedException e) {
    //Store my exception in a Map (this is all running in a loop and I want it to   continue running, but I also want to know which loops didn't complete and why)
   continue;
} 

Это предполагает, что вы будете обрабатывать ВСЕ эти проверенные исключения точно так же, как, конечно.

Ответ 1

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

Это действительно сводится к вашей ситуации. Если вам нужно сделать то же самое, когда MyCheckedException выбрано в любом случае, я бы счел его более читабельным и более эффективным, чтобы иметь их оба в одном блоке try, но если вам нужно обрабатывать две разные ситуации по-разному, то, конечно, имеет смысл разделить их.

Изменить: я прочитал конец вашего комментария, вы предполагаете обработку одинаково, и в этом случае я поместил бы их оба в один блок try.

Ответ 2

Рекомендуется ли поддерживать линии внутри try catch до минимума?

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

Является ли код внутри условия try работать медленнее или вызывать любую производительность хит?.

Нет.

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

Если вы беспокоитесь о производительности "try", наверняка все, что нужно сделать, это поддерживать максимальный код внутри?

Ответ 3

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

try {
    // op 1.
    // op 2.
    / ...
    // op n.
}
catch ( MyCheckedException error )
{
    // handle any `MyException` in op 1, 2 ... n.
}

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

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

Ответ 4

Наличие try-блоков должно иметь в основном нулевой эффект производительности в любой подходящей JVM. Настоящий хит приходит, когда на самом деле происходит исключение.

Вы можете прочитать эту статью, чтобы получить представление о том, как JVM реализует обработку исключений в байтекоде: он создает "таблицы исключений", которые отображают регионы кода для catch/finally блоков, поэтому:

  • Bytecode для блока try такой же, как для стандартного блока {} block
  • Единственная дополнительная стоимость в случае не бросания - это то, что в таблицу загружена "таблица исключений".

Конечно, когда генерируется исключение, происходит много работы с стеком, поэтому у него будет стоимость. В любом случае, это не так плохо, как с SEH (исключения .NET).

Ответ 5

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

Количество кода в блоке try не вызывает замедление, что делает блокировка блока catch. Но если вы не пытаетесь написать настоящий высокопроизводительный код, я бы не стал беспокоиться об этом.

Ответ 6

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

Ответ 7

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

Однако вы также должны учитывать разницу в семантике. В первом примере, если doSomething() выдает исключение, то doAnotherThing() не будет запущен. Во втором примере (при условии, что обработчик улова не возвращается), будет выполняться doAnotherThing().

Ответ 8

Я не уверен, что внутри блока try производительность может быть медленной, но я знаю, что производительность ex.getStackTrace() очень медленная, потому что она отображает весь ваш стек команд, и вы должны быть осторожны с этим.

Ответ 9

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

Представьте себе операцию переноса баланса, которая не получается в 1% случаев из-за отсутствия средств. Даже при такой относительно небольшой частоте отказов производительность может сильно пострадать.

См. исходный код и результаты тестов здесь.