Вот официальная страница начинающего от Mozilla для записи Вашего первого расширения. http://developer.mozilla.org/en/Building_an_Extension
Нет, вызов array.length
- это O (1)
или операция с постоянным временем.
Поскольку .length
является (действует как) public
final
членом массива
, доступ к нему не медленнее, чем к локальной переменной. (Это сильно отличается от вызова такого метода, как size ()
)
Современный JIT-компилятор, вероятно, в любом случае сразу оптимизирует вызов .length
.
Вы можете подтвердить это, просмотрев исходный код JIT-компилятора в OpenJDK или заставив JVM выгрузить собственный код, скомпилированный JIT, и изучив этот код.
Обратите внимание, что могут быть случаи, когда компилятор JIT не может этого сделать; например
У меня было немного времени за обедом:
public static void main(String[] args) {
final int[] a = new int[250000000];
long t;
for (int j = 0; j < 10; j++) {
t = System.currentTimeMillis();
for (int i = 0, n = a.length; i < n; i++) { int x = a[i]; }
System.out.println("n = a.length: " + (System.currentTimeMillis() - t));
t = System.currentTimeMillis();
for (int i = 0; i < a.length; i++) { int x = a[i]; }
System.out.println("i < a.length: " + (System.currentTimeMillis() - t));
}
}
Результаты:
n = a.length: 672
i < a.length: 516
n = a.length: 640
i < a.length: 516
n = a.length: 656
i < a.length: 516
n = a.length: 656
i < a.length: 516
n = a.length: 640
i < a.length: 532
n = a.length: 640
i < a.length: 531
n = a.length: 641
i < a.length: 516
n = a.length: 656
i < a.length: 531
n = a.length: 656
i < a.length: 516
n = a.length: 656
i < a.length: 516
Примечания:
n = a.length
показывает, что он быстрее, чем i примерно наполовину, вероятно, из-за сборки мусора (?).
250000000
намного больше, потому что я OutOfMemoryError
at 270000000
. Дело в том, и это то, что делали все остальные, вам нужно запустить Java из памяти, а вы все еще не видите значительная разница в скорости между двумя альтернативами. Тратьте свое время на разработку на действительно важные вещи.
Я сомневаюсь, что есть какая-то существенная разница, и даже если бы она была, я готов поспорить, что она, вероятно, была оптимизирована во время компиляции. Вы зря теряете время, пытаясь микрооптимизировать подобные вещи. Сначала сделайте код читаемым и правильным, затем, если у вас возникнут проблемы с производительностью, используйте профилировщик , затем позаботьтесь о выборе более эффективных структур данных / алгоритмов, если это необходимо, , затем побеспокоитесь об оптимизации частей. ваш профайлер выделяет.
Длина массива хранится как переменная-член массива (не такая же, как элемент) в Java, поэтому выборка этой длины является операцией с постоянным временем, такой же, как чтение переменная-член из обычного класса. Многие старые языки, такие как C и C ++, не хранят длину как часть массива, поэтому вам нужно сохранить длину до начала цикла. В Java этого делать не обязательно.
В таком случае, почему бы вам не сделать обратный цикл:
for (int i = a.length - 1; i >= 0; --i) {
...
}
Здесь есть 2 микрооптимизации:
Этот ответ дан с точки зрения C #, но я думаю, что то же самое относится и к Java.
В C # идиома
for (int i = 0; i < a.length; i++) { ...}
распознается как повторение по массиву, поэтому проверка границ избегается при доступе к массиву в цикле, а не при каждом доступе к массиву.
Это может или не может быть распознано с помощью такого кода, как:
for (int i = 0, n = a.length; i < n; i++) { ...}
или
n = a.length;
for (int i = 0; i < n; i++) { ...}
Какая часть этой оптимизации выполняется компилятор против JITter, которого я не знаю, и, в частности, если он выполняется JITter, я бы ожидал, что все 3 будут генерировать один и тот же собственный код.
Однако первая форма также, возможно, более читабельна для людей, поэтому Я бы сказал, продолжай.
Array.length является константой, и JIT-компилятор должен это видеть в обоих случаях. Я ожидал, что полученный машинный код будет одинаковым в обоих случаях. По крайней мере, для серверного компилятора.
Может быть, было бы немного быстрее сохранить его в переменной. Но я был бы крайне удивлен, если бы профилировщик указал на это как на проблему.
На уровне байт-кода получение длины массива выполняется с помощью байт-кода arrayylength
. Я не знаю, медленнее ли он, чем байт-код iload
, но разницы не должно быть достаточно, чтобы заметить.