Пример оптимизации проверки границ 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. Ожидается значение индекса за пределами допустимого диапазона, которое считается допустимым входным значением. В этом случае вы должны проверить и обработать это явно, как в примере1. Вам не нужно создавать какие-либо исключения в этом случае.

  2. Индекс выхода за границы является неожиданным (и, следовательно, является ошибкой в ​​вызывающем коде). Ваш код должен вызвать исключение здесь. Если вам нравится, вы можете перехватить и повторно сгенерировать исключение с помощью собственного сообщения, но вы также можете просто разрешить распространению исключения IndexOutOfBounds. Не беспокойтесь о влиянии на производительность этой обработки исключений - вы только что обнаружили ошибку и поэтому хотите, чтобы программа проваливалась так быстро и "громко", как только могла.....

Я не понимаю, как индекс, выходящий за границы, может быть нормальным состоянием. Либо в вашем алгоритме есть ошибка, либо вы неверно подтвердили ввод. И проверка ввода в этом случае заключается в проверке того, что индекс находится в границах. Проверка с помощью if (как в вашем первом фрагменте), очевидно, намного более читабелен, чист и эффективен, чем ловля исключения.

Другие вопросы по тегам