Производительность Java: длина массива против iload - PullRequest
3 голосов
/ 20 мая 2011
for (int i=0; i<arr.length; i++) {
}

Это приведет к коду:

getstatic   #4;
arraylength

Пока следующий код:

int length = arr.length;
for (int i=0; i<length; i++) {
}

будет скомпилировано как:

iload_3

Есть ли разница между двумя фрагментами? Какой код работает быстрее?

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

Ответы [ 3 ]

7 голосов
/ 20 мая 2011

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

В частности, если он может обнаружить, что массив не изменяется в цикле, он может избежать оценки длинынесколько раз и удаляют проверки границ массива в цикле - это может подтвердить, что вы никогда не получите доступ к массиву за пределами диапазона [0, length).

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

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

1 голос
/ 20 мая 2011

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

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

Форма, которую я использую при микрооптимизации:

for (int i = 0, length = methodCall(arr); i < length; i++) {
   // use the array.
}

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

1 голос
/ 20 мая 2011

Есть ли разница между двумя фрагментами?

Это зависит.Если переменная arr обновляется в теле цикла, то два фрагмента кода семантически различаются.

Какой код выполняется быстрее?

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

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