Статьи

Вы получаете сборник Just-in-time?

Помните последний раз, когда над вами смеялись разработчики C? Что Java настолько запутанный, что они никогда даже не подумают об использовании такого языка?

Во многих отношениях концепция по-прежнему имеет место. Но для его типичного использования — в магистралях большого предприятия — производительность Java определенно может противостоять многим конкурентам. И это возможно в основном благодаря магическому JIT.

Прежде чем приступить к объяснению приемов компиляции Just-In-Time, давайте немного углубимся в фон.

Как вы, наверное, помните, Java — это интерпретируемый язык. Компилятор Java, известный большинству пользователей, javac, не компилирует исходные файлы java непосредственно в инструкции процессора, как это делают компиляторы C. Вместо этого он создает байт-код, машинно-независимый двоичный формат, управляемый спецификацией . Этот байт-код интерпретируется во время выполнения JVM. Это основная причина успеха Java в кроссплатформенности — вы можете написать и собрать программу на одной платформе и запустить ее на нескольких других.
Just in Time
С другой стороны — это вносит некоторые негативные аспекты. Одним из наиболее серьезных является тот факт, что интерпретируемый код, как правило, медленнее, чем код, скомпилированный непосредственно в специфичные для платформы собственные двоичные файлы. Sun осознала серьезность этой проблемы уже в конце девяностых, когда наняла доктора Клиффа Клика, чтобы найти решение.

Добро пожаловать — HotSpot . Название происходит от способности JVM определять «горячие точки» в вашем приложении — фрагменты байт-кода, которые часто выполняются. Затем они предназначены для обширной оптимизации и компиляции в специфичные для процессора инструкции. Оптимизация приводит к высокопроизводительному выполнению с минимальными накладными расходами для менее критичного к производительности кода. В некоторых случаях адаптивная оптимизация JVM может превысить производительность кода C ++ или C, написанного вручную.

Компонент в JVM, отвечающий за эти оптимизации, называется компилятором Just in Time (JIT). Это использует интересное свойство программы. Практически все программы проводят большую часть своего времени, выполняя меньшую часть своего кода. Вместо того, чтобы компилировать весь ваш код, как раз вовремя, виртуальная машина Java HotSpot немедленно запускает программу с использованием интерпретатора и анализирует код во время работы, чтобы обнаружить критические горячие точки в программе. Затем он фокусирует внимание глобального оптимизатора нативного кода на горячих точках. Избегая компиляции нечасто исполняемого кода, компилятор Java HotSpot может уделять больше внимания критичным для производительности частям программы. Это означает, что ваше время компиляции не увеличивается в целом. Этот мониторинг горячих точек продолжается динамически во время работы программы, так что она адаптирует свою производительность на лету в соответствии со схемами использования вашего приложения.

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

Следующие примеры иллюстрируют те методы, которые используются JIT для достижения лучшей производительности. В первом разделе приведен код, написанный разработчиком. Во втором фрагменте кода показан код, выполняемый после того, как горячая точка обнаружила, что он «горячий», и применил магию оптимизации:

  1. Неоптимизированный код.
  2. 01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    class Calculator {
       Wrapper wrapper;
       public void calculate() {
          y = wrapper.get();
          z = wrapper.get();
          sum = y + z;
       }
    }
      
    class Wrapper {
       final int value;
       final int get() {
          return value;
       }
    }
  3. Оптимизированный код
  4. 01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    class Calculator {
       Wrapper wrapper;
       public void calculate() {
          y = wrapper.value;
          sum = y + y;
       }
    }
      
    class Wrapper {
       final int value;
       final int get() {
          return value;
       }
    }

Первый класс, описанный в небольшом примере выше, — это класс, написанный разработчиком, а второй — пример после того, как JIT завершил свою работу. Образец содержит несколько методов оптимизации. Давайте попробуем посмотреть, как достигается конечный результат:

  1. Неоптимизированный код. Это код, выполняемый до того, как он будет обнаружен как горячая точка:
  2. 1
    2
    3
    4
    5
    public void calculate() {
       y = wrapper.get();
       z = wrapper.get();
       sum = y + z;
    }
  3. Встраивание метода. wrapper.get () был заменен на b.value, поскольку задержки уменьшаются путем прямого доступа к wrapper.value вместо вызова функции.
  4. 1
    2
    3
    4
    5
    public void calculate() {
       y = wrapper.value;
       z = wrapper.value;
       sum = y + z;
    }
  5. Удаление лишних нагрузок. z = wrapper.value был заменен на z = y, так что задержки будут уменьшены путем доступа к локальному значению вместо wrapper.value .
  6. 1
    2
    3
    4
    5
    public void calculate() {
       y = wrapper.value;
       z = y;
       sum = y + z;
    }
  7. Копирование распространения. z = y был заменен на y = y, поскольку дополнительная переменная z не используется, так как значения z и y будут равны.
  8. 1
    2
    3
    4
    5
    public void calculate() {
       y = wrapper.value;
       y = y;
       sum = y + y;
    }
  9. Устранение мертвого кода. y = y не является необходимым и может быть устранено.
  10. 1
    2
    3
    4
    public void calculate() {
       y = wrapper.value;
       sum = y + y;
    }

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

Для этой статьи были использованы следующие ссылки (кроме двух разгневанных разработчиков C):

Справка: Вы получаете сборник Just-in-time? от нашего партнера JCG Никиты Сальникова Тарновского в блоге Plumbr Blog .