Итеративная скорость интервала по сравнению с долго

У меня есть следующие две программы:

long startTime = System.currentTimeMillis();
for (int i = 0; i < N; i++);
long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");

и

long startTime = System.currentTimeMillis();
for (long i = 0; i < N; i++);
long endTime = System.currentTimeMillis();
System.out.println("Elapsed time: " + (endTime - startTime) + " msecs");

Примечание: единственной разницей является тип переменной цикла (int и long).

Когда я выполняю это, первая программа последовательно печатает между 0 и 16 национальной безопасностью, независимо от значения N. Вторые взятия намного дольше. Для N == Integer.MAX_VALUE, это работает приблизительно в 1 800 национальной безопасности на моей машине. Время выполнения, кажется, более или менее линейно в N.

Итак, почему это?

Я предполагаю, что JIT-компилятор оптимизирует int цикл до смерти. И на серьезном основании, потому что, очевидно, это ничего не делает. Но почему это не делает так для long цикл также?

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

Я использую JDK 1.6.0 обновлений 17:

C:\>java -version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)

Я нахожусь на Выпуске Windows XP Professional x64, Пакет обновления 2, с Intel Core2 Quad CPU на уровне 2.40 ГГц.


Отказ от ответственности

Я знаю, что микросравнительные тесты не полезны в производстве. Я также знаю это System.currentTimeMillis() не так точно, как его имя предлагает. Это - просто что-то, что я заметил при дурачении, и мне было просто любопытно относительно того, почему это происходит; ничто больше.

8
задан jqno 9 April 2010 в 09:17
поделиться

4 ответа

Это интересный вопрос, но, честно говоря, я не уверен, что рассмотрение поведения Hotspot здесь даст полезную информацию. Любые ответы, которые вы получите, не будут передаваться в общем случае (потому что мы смотрим на оптимизацию, которую Hotspot выполняет в одной конкретной ситуации), поэтому они помогут вам понять, почему одна не-операция быстрее, чем другая, но они не помогут вам писать более быстрые «настоящие» программы .

Также невероятно легко написать очень вводящие в заблуждение микротесты для такого рода вещей - см. эту статью IBM DW , где описаны некоторые из распространенных ошибок, как их избежать, а также некоторые общие комментарии о том, что вы делает.

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

5
ответ дан 5 December 2019 в 12:57
поделиться

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

Также обратите внимание, что значения системных часов, которые вы получаете с помощью System.currentTimeMillis () , не имеют разрешения в 1 мс во всех операционных системах. Вы не можете использовать это для очень точного определения времени очень коротких событий.

Прочтите эту статью, в которой объясняется, почему выполнение микротестов на Java не так просто, как думает большинство людей: Анатомия некорректного микробенча

1
ответ дан 5 December 2019 в 12:57
поделиться

Вы, вероятно, используете 32-битную JVM. Результаты, вероятно, будут другими с 64-битной JVM. В 32-битной JVM int можно сопоставить с собственным 32-битным целым числом и увеличить с помощью одной операции. То же самое продлится недолго, и для увеличения потребуется больше операций.

См. Этот вопрос для обсуждения размеров int и long.

4
ответ дан 5 December 2019 в 12:57
поделиться

Мое предположение - и это только предположение - таково:

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

Во втором случае цикл также ничего не делает. Но может оказаться, что в коде JVM, который определяет, что цикл ничего не делает, есть пункт "if (type of i) == int". В этом случае оптимизация для удаления ничего не делающего цикла for-loop работает только с int.

Оптимизация, удаляющая код, должна быть уверена в отсутствии побочных эффектов. Похоже, что разработчики JVM проявили осторожность.

3
ответ дан 5 December 2019 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: