Translate

понеділок, 24 грудня 2012 р.

JIT. Intro


Пам'ятаєте, коли в останній раз з вас "сміялися" розробник C/С++ ? З того, що Java є безнадійно повільною?

В дечому вони праві. Але в багатьох випадках Java може посперечатись в продуктивності/швидкодії з багатьма суперниками. І це можливо в основному завдяки магії JIT.

Перш ніж перейти до пояснень Just-In-Time магії компіляції, дозвольте додати невеликий історичний екскурс.

Як ви, можливо, пам'ятаєте - Java є інтерпретованою мовою. Java-компілятор javac, не компілює файли вихідного коду Java безпосередньо в процесорні інструкції, як компілятори С. Замість цього він продукує байт-код, машинно-незалежного бінарний формат, який відповідає специфікації. Цей байт-код інтерпретується JVM. Це є основною причиною, чому Java є настільки успішною як крос-платформена мова програмування. Ви можете написати програму на одній платформі і запускати її на безлічі інших.

З іншого боку - це додає деякі негативні аспекти. Один з них є те, що інтерпретований код  зазвичай повільніше, ніж код скомпільований безпосередньо для конкретної платформи. Sun зрозумів всю серйозність в кінці дев'яностих, коли найняв dr Cliff Click, щоб знайти рішення цієї проблеми.


І наслідком цього + купівлі невеликої компанії стала - VM HotSpot. Назва походить від здатності JVM  виявляти "гарячих точок" у вашому коді - шматки байт-коду, які часто виконуються. Які потребують оптимізації та компіляції в конкретні інструкцій процесора. Оптимізація приводить до високої продуктивності виконання коду при мінімальному накладних витратах. У деяких випадках, оптимізація коду JVM може перевищувати продуктивність коду написаного на C + + або C.


Компонент JVM відповідльний за оптимізацію називається Just In Time компілятор (JIT). Він використовує цікаву властивість програми. Практично всі програми витрачають більшість часу на виконання невелико кількості коду (правило 80/20). Java HotSpot VM: при старті запускає програму і за допомогою інтерпретатора виконує її + паралельно аналізує код, щоб визначити критичні гарячі точки в ній. В залежності від типу і налаштувань конкретної VM спосіб аналізу відрізняється. В момен, коли VM має достатню к-сть інформації вона компілює "гарячий" шматок коду.

JIT забезпечує виграш в продуктивності кількома шляхами:
  • мертвого коду
  • минаючи перевірку граничних умов
  • inlining methods 
  • і т.д.
Наступні приклади ілюструють методи, використовувані JIT для досягнення більш високої продуктивності.

Не оптимізований код:

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;
   }
}

Оптимізований код:

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. Неоптимізованих код. Цей код, виконується до його компіляції:

public void calculate() {
   y = wrapper.get();
   z = wrapper.get();
   sum = y + z;
}

2. Inlining методу wrapper.get() - був замінений на b.value. Зменшився час доступ до wrapper.value через усунення виклику метода.

public void calculate() {
   y = wrapper.value;
   z = wrapper.value;
   sum = y + z;
}

3. Видалення надлишкових викликів. z = wrapper.value була замінена z = у, зменьшиться час доступу до локальної змінної.


public void calculate() {
   y = wrapper.value;
   z = y;
   sum = y + z;
}

4. Копіювання змінних. z = у була замінена у = у, так як немає ніякого сенсу мати дві змінні з однаковими значеннями.

public void calculate() {
   y = wrapper.value;
   y = y;
   sum = y + y;
}

5. Усунення мертвого коду. у = у є надлишковим і може бути усунений.

public void calculate() {
   y = wrapper.value;
   sum = y + y;
}


Для написання статті використовувались ось ці лінки:
http://www.oracle.com/technetwork/java/whitepaper-135217.html
http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html
http://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/underst_jit.html

А оригінал статті можна знайти ось тут:
http://www.javacodegeeks.com/2012/12/do-you-get-just-in-time-compilation.html

ПС.
Як завжди:
  • коментарі вітаються :)
  • можливо хтось хоче розвинути тему???
  • Якщо знайдете помилки - пишіть. Виправлю.
  • Стаття ввідна і розрахована на знайомство з JIT.
Можливо у Вас виникло запитання, а де можна подивитись правила за якими код оптимізується?

А я вам відповім, що я такого опису 100% повного не знайшов... . + JIT різні реалізації, які працюють по різному.
Але якщо Ви знаєте щось таке - пишіть.
А від себе додам, що стандарти написання Java коду зроблені не тільки для краси і четабельності, але й для полегшення роботи програмі JIT. Схожі думки маю і про патерни.