Производительность 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;
} 

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

9 ответов


в вашем примере здесь реальный хит производительности, если оба doSomething() и doAnotherThing() выбрасывают исключения. Ввод блока try-block выполняется быстро, пока он не выдаст исключение.

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

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


рекомендуется ли сохранить строки внутри попробуйте поймать до минимума?

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

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

нет.

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

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


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

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

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

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


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

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

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

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


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

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


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


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

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


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

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

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


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