Сохраняет ли Java свои оптимизации времени выполнения? - PullRequest
4 голосов
/ 16 сентября 2008

Мой профессор провел неофициальный тест для небольшой программы, и время Java составило: 1,7 секунды для первого запуска и 0,8 секунды для последующих прогонов.

  • Это связано исключительно с загрузкой среды выполнения в операционную среду?

    ИЛИ

  • На это повлияла оптимизация кода Java и сохранение результатов этих оптимизаций (извините, я не знаю технического термина для этого)?

Ответы [ 6 ]

5 голосов
/ 16 сентября 2008

Хорошо, я нашел, где я это читал. Это все из «Изучения Java» (O'Reilly 2005):

Проблема с традиционной JIT-компиляцией заключается в том, что оптимизация кода требует времени. Таким образом, JIT-компилятор может давать приличные результаты, но может иметь значительные задержки при запуске приложения. Как правило, это не проблема для долго работающих серверных приложений, но это серьезная проблема для клиентского программного обеспечения и приложений, запускаемых на небольших устройствах с ограниченными возможностями. Для решения этой проблемы технология компиляции Sun, называемая HotSpot, использует прием, называемый адаптивной компиляцией. Если вы посмотрите на то, на что на самом деле тратят программы, оказывается, что они тратят почти все свое время на выполнение сравнительно небольшой части кода снова и снова. Кусок кода, который выполняется многократно, может составлять лишь небольшую часть всей программы, но его поведение определяет общую производительность программы. Адаптивная компиляция также позволяет среде выполнения Java использовать преимущества новых видов оптимизации, которые просто невозможно выполнить на статически скомпилированном языке, поэтому в некоторых случаях утверждается, что код Java может выполняться быстрее, чем C / C ++.

Чтобы воспользоваться этим фактом, HotSpot запускается как обычный интерпретатор байт-кода Java, но с отличием: он измеряет (профилирует) код во время его выполнения, чтобы увидеть, какие части выполняются повторно. Как только он узнает, какие части кода имеют решающее значение для производительности, HotSpot компилирует эти разделы в оптимальный машинный код. Поскольку он компилирует только небольшую часть программы в машинный код, он может позволить себе потратить время, необходимое для оптимизации этих частей. Остальная часть программы может не скомпилироваться вообще - только что интерпретированная - экономия памяти и времени. На самом деле Java VM по умолчанию Sun может работать в одном из двух режимов: клиент и сервер, которые сообщают ему, следует ли подчеркивать быстрое время запуска и сохранение памяти или снижать производительность.

Естественный вопрос, который следует задать в этот момент: зачем выбрасывать всю эту хорошую информацию о профилировании каждый раз, когда приложение закрывается? Что ж, Sun частично затронула эту тему с выпуском Java 5.0 благодаря использованию общих классов только для чтения, которые постоянно хранятся в оптимизированной форме. Это значительно сокращает время запуска и накладные расходы на запуск многих приложений Java на данном компьютере. Технология для этого сложна, но идея проста: оптимизируйте те части программы, которые должны работать быстро, и не беспокойтесь об остальном.

Мне интересно, как далеко продвинулась Sun с Java 5.0.

4 голосов
/ 16 сентября 2008

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

То, что вы видите, почти наверняка связано с кэшированием диска.

2 голосов
/ 16 сентября 2008

Я согласен, что это скорее всего результат кеширования диска.

Между прочим, виртуальная машина IBM Java 6 содержит опережающий компилятор (AOT). Код не так оптимизирован, как JIT, но он хранится в виртуальных машинах, я полагаю, в некоторой постоянной памяти. Его основным преимуществом является повышение производительности при запуске. Виртуальная машина IBM по умолчанию JITs метод после того, как он был вызван 1000 раз. Если он знает, что метод будет вызываться 1000 раз непосредственно во время запуска виртуальной машины (представьте себе обычно используемый метод, такой как java.lang.String.equals(...)), тогда полезно сохранить его в кеше AOT, чтобы он никогда не терял впустую. время компиляции во время выполнения.

1 голос
/ 16 сентября 2008

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

Если вы включите время запуска JVM (которое полезно для сравнительного анализа пользовательского интерфейса, но не очень полезно для оптимизации кода Java), то это может быть эффект кэширования файловой системы или он может быть вызван функцией под названием «Обмен данными Java-класса». «:

Для Солнца:

http://java.sun.com/j2se/1.5.0/docs/guide/vm/class-data-sharing.html

Это вариант, когда JVM сохраняет подготовленный образ классов времени выполнения в файл, чтобы обеспечить более быструю загрузку (и совместное использование) классов при следующем запуске. Вы можете управлять этим с помощью -Xshare: on или -Xshare: off с помощью Sun JVM. По умолчанию используется -Xshare: auto, который загружает образ совместно используемых классов, если он присутствует, и, если его нет, записывает его при первом запуске, если каталог способен к записи.

С IBM Java 5 это, кстати, еще мощнее:

http://www.ibm.com/developerworks/java/library/j-ibmjava4/

Я не знаю ни одной основной JVM, которая бы сохраняла статистику JIT.

1 голос
/ 16 сентября 2008

Я согласен с тем, что разница в производительности, наблюдаемая на плакате, скорее всего, вызвана задержкой диска, приводящей JRE в память. Компилятор Just In Time (JIT) не будет влиять на производительность небольшого приложения.

Java 1.6u10 (http://download.java.net/jdk6/) касается файлов JAR времени выполнения в фоновом процессе (даже если Java не работает), чтобы сохранить данные в дисковом кэше. Это значительно сокращает время запуска (что является огромным преимуществом) к настольным приложениям, но, вероятно, имеют предельную ценность для серверных приложений).

В больших и долго работающих приложениях JIT имеет большое значение во времени, но количество времени, необходимое JIT для накопления достаточной статистики для включения и оптимизации (5-10 секунд), очень и очень мало по сравнению с общий срок службы приложения (большинство работает в течение нескольких месяцев и месяцев). Хотя сохранение и восстановление результатов JIT является интересным академическим упражнением, практическое улучшение не очень велико (вот почему команда JIT была более сосредоточена на таких вещах, как стратегии GC для минимизации пропусков кеш-памяти и т. Д.). *

Предварительная компиляция классов времени выполнения очень помогает настольным приложениям (как и вышеупомянутая предварительная загрузка дискового кэша 6u10).

0 голосов
/ 16 сентября 2008

Java JVM (фактически может отличаться от разных реализаций JVM) при первом запуске будет интерпретировать байт-код. Как только он обнаруживает, что код будет запущен достаточное количество раз, он JIT переводит его на машинный язык, чтобы он работал быстрее.

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