Пример оптимизации проверки границ Java
Я читал, что некоторые из JVM могут оптимизировать выполнение кода, удалив проверку границ. Я пытаюсь понять, какая техника кодирования будет работать лучше.
В методе example1 ниже JVM когда-нибудь выяснит это и исключит проверку границ ссылки на источник [индекс]?
Пример2 - лучшая практика кода? Казалось бы, но в некоторых алгоритмах внутри цикла индекс вне границ является нормальным условием. Таким образом, вы не хотите генерировать тонны объектов Exception внутри этого цикла.
public void example1(int [] source, int index) {
if (index >= 0 && index < source.length)
System.out.println("Value is " + source[index]);
else
System.out.println("Out of range: " + index);
}
public void example2(int [] source, int index) {
try {
System.out.println("Value is " + source[index]);
} catch (IndexOutOfBoundsException exp) {
System.out.println("Out of range: " + index);
}
}
Эти фрагменты кода являются только репрезентативными. Я знаю, что в этих примерах проверка границ вряд ли будет иметь значение для производительности. Однако я работаю над приложением со встроенным протоколом, в котором будет добавлена избыточная проверка границ.
2 ответа
На ваш первый вопрос в примере 1 теоретически можно устранить проверку границ. Я ожидал бы, что лучшие современные JIT-компиляторы сделают это (например, возможно, путем исключения общего подвыражения при проверке границ при расширении source[index]). Как обычно, это зависит от реализации, поэтому вы не можете на это полагаться. OTOH, даже если проверка границ не устранена, разница будет тривиальной - вы попадаете в уже кэшированную область памяти для source.length и выполняете несколько целочисленных сравнений, поэтому накладные расходы незначительны.
example2 не является хорошей практикой - вы нажимаете исключение, но затем его ловите и продолжаете, как будто ничего не произошло. Если вы не смотрите внимательно stdout, вы можете полностью упустить тот факт, что в вашем коде есть ошибка.
В основном есть две общие "хорошие" возможности в зависимости от того, что вы считаете допустимым входным значением для "индекса":
Ожидается значение индекса за пределами допустимого диапазона, которое считается допустимым входным значением. В этом случае вы должны проверить и обработать это явно, как в примере1. Вам не нужно создавать какие-либо исключения в этом случае.
Индекс выхода за границы является неожиданным (и, следовательно, является ошибкой в вызывающем коде). Ваш код должен вызвать исключение здесь. Если вам нравится, вы можете перехватить и повторно сгенерировать исключение с помощью собственного сообщения, но вы также можете просто разрешить распространению исключения IndexOutOfBounds. Не беспокойтесь о влиянии на производительность этой обработки исключений - вы только что обнаружили ошибку и поэтому хотите, чтобы программа проваливалась так быстро и "громко", как только могла.....
Я не понимаю, как индекс, выходящий за границы, может быть нормальным состоянием. Либо в вашем алгоритме есть ошибка, либо вы неверно подтвердили ввод. И проверка ввода в этом случае заключается в проверке того, что индекс находится в границах. Проверка с помощью if
(как в вашем первом фрагменте), очевидно, намного более читабелен, чист и эффективен, чем ловля исключения.