Що робить щойно вчасно (JIT) компілятор?


528

Що конкретно робить компілятор JIT на відміну від компілятора, який не є JIT? Чи може хтось дати короткий і простий для розуміння опис?




2
Я вважаю youtube.com/watch?v=yQ27DjKnxwo корисним.
Адам Зернер

Відповіді:


518

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

Це на відміну від традиційного компілятора, який збирає весь код на машинну мову до першого запуску програми.

Якщо перефразовувати, звичайні компілятори будують всю програму як файл EXE перед тим, як запустити її. Для нових програм стилю створюється збірка з псевдокодом (p-кодом). Тільки ПІСЛЯ ви виконаєте програму в ОС (наприклад, двічі клацнувши на її значку), компілятор (JIT) запустить і генерує машинний код (m-код), який буде розбиратися процесором на базі Intel.


16
І на відміну від інтерпретованого коду, який починає виконувати байт-код або інструкції VM негайно без затримки, але запускатиме інструкції повільніше, ніж машинна мова.
Аарон

3
JIT часто використовується з інтерпретованим кодом для перетворення його на машинну мову, але так, чисто інтерпретований код (без жодного JITting) відбувається повільно. Навіть байт-код Java без JITter дійсно повільний.
Марк Сідаде

48
Однак ціль не повинна бути машинним кодом. У JRuby є компілятор JIT, який буде компілювати вихідний код Ruby в байт-код Java після пари викликів. Потім, після ще однієї виклику, компілятор JVM JIT запускає і компілює байт-код до нативного коду.
Йорг W Міттаг,

4
Варто зазначити, що, як наголошував Йорг, JIT не обов'язково використовується відразу. Часто код буде інтерпретуватися до тих пір, поки не буде визначено, що він буде вартим JITting. Оскільки JITting може вводити затримки, можливо, швидше НЕ JIT деякого коду, якщо він використовується рідко, і, таким чином, швидка реакція важливіша, ніж загальний час виконання.
Адам Яскевич

3
@ErikReppen: Якщо вийде нова машина, компіляція та оптимізація програми для цієї нової машини за допомогою звичайного компілятора, швидше за все, дасть результати швидше, ніж JIT. З іншого боку, JIT, оптимізований для цієї нової машини, зможе оптимізувати продуктивність коду, який був опублікований до винайдення цієї нової машини .
supercat

255

На початку компілятор відповідав за перетворення мови високого рівня (визначеного як вищий рівень, ніж асемблер), в об'єктний код (машинні інструкції), який потім буде пов'язаний (за допомогою лінкера) у виконуваний файл.

У один момент еволюції мов компілятори склали мову високого рівня в псевдо-код, який потім був би інтерпретований (інтерпретатором) для запуску вашої програми. Це усунуло об'єктний код та виконувані файли та дозволило переносити ці мови на кілька операційних систем та апаратних платформ. Паскаль (який складено до P-Code) був одним із перших; Java та C # - більш пізні приклади. Врешті-решт термін P-Code був замінений на байт-код, оскільки більшість псевдооперацій є байтовими.

Компілятор Just-In-Time (JIT) - це особливість інтерпретатора виконання, який замість інтерпретації байт-коду кожного разу, коли викликується метод, буде збирати байт-код в інструкції машинного коду запущеної машини, а потім викликати це об'єктний код замість цього. В ідеалі ефективність запущеного об'єктного коду подолає неефективність перекомпіляції програми кожного разу, коли вона запускається.


5
Однак ця фраза "компілятор Just-In-Time (JIT) - особливість інтерпретатора виконання)" викликає плутанину; наприклад - stackoverflow.com/questions/16439512/…
Стівен C

11
Насправді JIT був надбудовою, і ви все одно можете відключити його за допомогою параметра -Xint для Java, тому це лише функція.
Крейг Трейдер

3
Я не повністю згоден. JIT - це не еволюція - це альтернатива класичним компіляторам.
i486

1
JIT - це один крок на еволюційному шляху від механічних перемикачів жорсткої проводки до визначення критеріїв пошуку, сказавши "OK Google" на ваш смартфон. Поточний JIT, доступний як частина Java 7/8, є стрибками та межами того, що було доступно як частина Java 2 - це теж еволюція.
Крейг Трейдер

1
@ i486 - Sun / Oracle ніколи (AFAIK) ніколи не постачав класичний ("достроково") компілятор для Java, який генерує власний код. Це тягнеться стверджувати, що JIT є альтернативою ... коли вони рішають, це нібито альтернатива ніколи не постачалася. (Я знижую компілятор GCJ AOT, тому що це не було нічого спільного з Sun / Oracle, і це також не було повним рішенням. Це, безумовно, зараз нежиттєздатне.)
Stephen C

69

JIT - саме вчасно слово говорить саме тоді, коли це потрібно (на вимогу)

Типовий сценарій:

Вихідний код повністю перетворюється в машинний код

Сценарій JIT:

Вихідний код буде перетворений на мову складання, як структура [для колишнього IL (проміжна мова) для C #, ByteCode для Java].

Проміжний код перетворюється на машинну мову лише тоді, коли потрібні додатки, які необхідні коди перетворюються лише на машинний код.

Порівняння JIT проти Non-JIT:

  • У JIT не весь код перетворюється в машинний код, спочатку частина коду, яка необхідна, буде перетворена в машинний код, потім, якщо названий метод або функціональність не є в машині, то він буде перетворений на машинний код ... він зменшується тягар на процесор.

  • Оскільки машинний код буде генеруватися під час виконання .... компілятор JIT створить машинний код, оптимізований для роботи архітектури ЦП машини.

Приклади JIT:

  1. У Java JIT знаходиться в JVM (віртуальна машина Java)
  2. У C # він знаходиться в CLR (загальна мова виконання)
  3. В Android він знаходиться у DVM (Dalvik Virtual Machine) або ART (Android RunTime) у нових версіях.

7
JIT пропонує деякі особливі переваги в рамках з підтримкою реальних загальних типів; можна визначити загальний метод, який міг би створювати необмежений діапазон типів, кожен з яких потребував би різного машинного коду, але матиме лише код генерування JIT для типів, які фактично виробляються. Навпаки, в C ++ необхідно, щоб компілятор генерував код для всіх типів, які програма коли-небудь використовуватиме.
supercat

6
JVM не кодує JIT при першому його запуску. Перші кілька разів він інтерпретує байт-код. Тоді, якщо цей код працює досить часто, він може вирішити потурбувати його JITting.
ніндзя

1
Ви говорите, що JIT на Java - JVM. Однак ми вже надаємо компільований код JVM, чи не так? Тоді він знову це компілює?
Корай Тугай

@KorayTugay - Ми надаємо Bytecodes JVM, а JVM перетворить частину цього в машинний код на вимогу.
Дурай Амутан.H

1
У Java JIT не є JVM. Це лише її частина.
хапс

25

Як згадували інші

JIT означає Just-in-Time, що означає, що код збирається тоді, коли це потрібно, а не перед виконанням.

Просто, щоб додати крапку до вищезгаданого обговорення, JVM підтримує підрахунок, скільки разів виконується функція. Якщо ця кількість перевищує попередньо визначений ліміт, JIT компілює код на машинну мову, який може бути безпосередньо виконаний процесором (на відміну від звичайного випадку, коли javac компілює код у байт-код, а потім у java - інтерпретатор інтерпретує цей рядок байт-коду за рядком, перетворює його в машинний код і виконує).

Також наступного разу, коли ця функція обчислюється, знову складається такий же складений код на відміну від звичайної інтерпретації, в якій код інтерпретується знову за рядком. Це робить виконання швидшим.


14

Компілятор JIT компілює лише байт-код до еквівалентного нативного коду при першому виконанні. Після кожного наступного виконання JVM просто використовує вже складений нативний код для оптимізації продуктивності.

введіть тут опис зображення

Без компілятора JIT інтерпретатор JVM перекладає байт-код рядок за рядком, щоб виглядати так, ніби виконується нативна програма.

введіть тут опис зображення

Джерело


1
Моя інтерпретація JIT полягає в тому, що він діє як запам'ятовування, де часто використовувані функції "зберігаються", а витрата компіляції з байт-коду Java в нативний ISA-залежний код обходить. Якщо це правильно, чому java не компілюється повністю до нативного коду з самого початку? Це зменшило б будь-яку компіляцію часу виконання та зробило java "рідною" для машини?
Майкл Чой

12

JIT означає Just-in-Time, що означає, що код збирається тоді, коли це потрібно, а не перед виконанням.

Це вигідно, оскільки компілятор може генерувати код, оптимізований для вашої конкретної машини. Статичний компілятор, як і ваш середній компілятор С, буде компілювати весь код на виконуваний код на машині розробника. Отже, компілятор проведе оптимізацію на основі деяких припущень. Він може компілювати повільніше і робити більше оптимізацій, оскільки це не уповільнює виконання програми для користувача.


Чому не компільовані коди зберігаються десь на комп'ютері користувача, тому наступного разу, коли програма запущена, JIT не доведеться їх перекомпілювати знову?
omerfarukdogan

Хороші спостереження. Це можна зробити, але чи буде це вигідно, залежить від платформи та використання програми. Оптимізація JIT не обов'язково така сама, як офлайн або поза часом оптимізації, тому вигода може бути лише «не JITting», що може або не дуже допоможе.
Брайан Латтл

9

Після створення байтового коду (який є нейтральним для архітектури) компілятором Java, виконанням буде керуватися JVM (на Java). Код байта завантажується в JVM завантажувачем, після чого інтерпретується кожна байтна інструкція.

Коли нам потрібно викликати метод кілька разів, нам потрібно тлумачити один і той же код багато разів, і це може зайняти більше часу, ніж потрібно. Отже, у нас є компілятори JIT (щойно вчасно). Коли байт буде завантажений у JVM (його час запуску), весь код буде складений, а не інтерпретований, таким чином заощаджуючи час.

Компілятори JIT працюють тільки під час виконання, тому у нас немає жодного бінарного виводу.


2
Весь код не компілюється при завантаженні в JVM, оскільки мало інформації (читайте: посібник) про те, як пройти компіляцію. Майте на увазі, що ефективність - це кінцева мета. JIT є досить вибірковим: моніторинг та вибір найпопулярніших методів оптимізації. І це продовжує робити, поки не буде досягнуто максимального рівня оптимізації для окремих методів.
Yaw Boakye

7

Компілятор Just In Time (JIT):
він компілює байт-коди Java в машинні інструкції цього конкретного процесора.

Наприклад, якщо в нашому Java-коді є заява циклу:

while(i<10){
    // ...
    a=a+i;
    // ...
 }

Вищенаведений код циклу працює 10 разів, якщо значення i дорівнює 0.

Не потрібно збирати байт-код 10 разів знову і знову, оскільки та сама інструкція буде виконуватися 10 разів. У такому випадку потрібно скомпілювати цей код лише один раз, і значення можна змінити на необхідну кількість разів. Отже, компілятор Just In Time (JIT) відслідковує такі твердження та методи (як було сказано вище) і компілює такі фрагменти байтового коду в машинний код для кращої продуктивності.

Іншим подібним прикладом є пошук шаблону за допомогою "Regular Expression" у списку рядків / пропозицій.

Компілятор JIT не компілює весь код до машинного коду. Він компілює код, який має аналогічну схему під час виконання.

Дивіться цю документацію Oracle на Understand JIT, щоб прочитати більше.


"Не потрібно збирати байт-код 10 разів знову і знову, оскільки та сама інструкція збирається виконувати 10 разів" - як щодо звичайного компілятора? Чи складає цей твір кілька разів?
TT_

4

У вас є код, сумісний з якоюсь ІЛ (проміжною мовою). Під час запуску програми комп'ютер не розуміє цього коду. Він розуміє лише нативний код. Тож компілятор JIT збирає ваш IL в нативний код на льоту. Це робиться на рівні методу.


2
Що ви маєте на увазі "рівень методу"?
Корай Тугай

4

Я знаю, що це стара тема, але оптимізація виконання - ще одна важлива частина компіляції JIT, яка, здається, не обговорюється тут. В основному компілятор JIT може контролювати програму під час її запуску для визначення шляхів покращення виконання. Тоді вони можуть внести ці зміни під час руху - під час виконання. Оптимізація Google JIT (у javaworld є досить гарна стаття про це. )


3

Щойно вчасно компілятор (JIT) - це програмне забезпечення, яке приймає отримує не виконаний вхід і повертає відповідний машинний код, який потрібно виконати. Наприклад:

Intermediate representation    JIT    Native machine code for the current CPU architecture

     Java bytecode            --->        machine code
     Javascript (run with V8) --->        machine code

Наслідком цього є те, що для певної архітектури процесора повинен бути встановлений відповідний компілятор JIT.

Компілятор, перекладач та JIT

Хоча в цілому можуть бути винятки, коли ми хочемо перетворити вихідний код у машинний код, ми можемо використовувати:

  1. Компілятор : Бере вихідний код і повертає виконуваний файл
  2. Інтерпретатор : Виконує інструкцію програми за інструкцією. Він займає виконуваний сегмент вихідного коду і перетворює цей сегмент в машинні інструкції. Цей процес повторюється до тих пір, поки весь вихідний код не буде перетворений на машинні інструкції та виконаний.
  3. JIT : Можливе багато різних реалізацій JIT, однак JIT зазвичай є комбінацією компілятора та інтерпретатора. JIT спочатку перетворює посередницькі дані (наприклад, байт-код Java), які він отримує в машинну мову через інтерпретацію. JIT часто може відчувати, коли певна частина коду виконується часто, і воля складе цю частину для швидшого виконання.

2

Jit означає щойно вчасно компілятор jit - це програма, яка перетворює Java-байт-код в інструкцію, яку можна направити безпосередньо на процесор.

Використання компілятора Java щойно (справді другий компілятор) на конкретній системній платформі відповідає байтовому коду до конкретного системного коду, після того як код буде перекомпільований компілятором jit, він, як правило, швидше працюватиме на комп'ютері.

Щойно вчасно компілятор постачається з віртуальною машиною і використовується необов'язково. Він компілює байтовий код у визначений для платформи код, який негайно виконується.


2

компіляція щойно вчасно (JIT) (також динамічний переклад або компіляція під час виконання ) - це спосіб виконання комп'ютерного коду, який передбачає компіляцію під час виконання програми - під час виконання програми - а не до її виконання .

ІТ-компіляція - це поєднання двох традиційних підходів до перекладу машинного коду - дострокової компіляції (AOT) та інтерпретації - та поєднує деякі переваги та недоліки обох. Компіляція JIT поєднує швидкість компільованого коду та гнучкість інтерпретації .

Розглянемо JIT, що використовується в JVM,

Наприклад, компілятори HotSpot JVM JIT генерують динамічні оптимізації. Іншими словами, вони приймають рішення щодо оптимізації під час роботи програми Java та генерують високоефективні інструкції з власної машини, орієнтовані на базову архітектуру системи.

Коли метод обраний для компіляції, JVM подає свій байт-код до компілятора Just-In-Time (JIT). JIT повинен зрозуміти семантику та синтаксис байт-коду, перш ніж він зможе правильно скомпілювати метод. Щоб допомогти компілятору JIT проаналізувати метод, його байт-код спочатку переформулюється у внутрішнє представлення, яке називається деревами слідів, яке нагадує машинний код ближче, ніж байт-код. Потім аналіз та оптимізація проводяться на деревах методу. Наприкінці дерева переводяться у рідний код.

Дерево слідів - це структура даних, яка використовується при компіляції коду програмування. Дерева слідів використовуються у типі "компілятора просто в часі", який відстежує код, який виконується під час гарячих точок, та компілює його. Зверніться до цього .

Посилання:


1

Компілятор, який не є JIT, приймає вихідний код і перетворює його в специфічний машинний байтний код під час компіляції. Компілятор JIT бере машинний агностичний байт-код, який був сформований під час компіляції та перетворює його в специфічний машинний байт-код під час виконання. Компілятор JIT, який використовує Java, - це те, що дозволяє одному бінарному файлу працювати на безлічі платформ без змін.


0

20% байтового коду використовується 80% часу. Компілятор JIT отримує ці статистичні дані і оптимізує цей 20% байтового коду для швидшого запуску шляхом додавання вбудованих методів, видалення невикористаних замків тощо, а також створення байтового коду, характерного для цієї машини. Цитую цю статтю, я виявив, що це зручно. http://java.dzone.com/articles/just-time-compiler-jit-hotspot


Не впевнений, чому це було позначено -1. Я думаю, що справа тут у тому, що статистика часу виконання використовується для оптимізації.
eze

Так, але у відповіді це не було так. Буквально JIT не оптимізує найгарячіші 20% коду.
мабрахам

0

JIT посилається на механізм виконання у кількох реалізаціях JVM, той, який швидший, але вимагає більше пам’яті, - це щойно створений компілятор. У цій схемі байт-коди методу складаються до власного машинного коду при першому виклику методу. Після цього кешується нативний машинний код методу, тому він може бути використаний повторно наступного разу, коли буде використаний той самий метод.


2
Я б уникну відповіді на подібне запитання, якщо ви не надасте щось нове / краще. Якщо ви отримаєте будь-яку реакцію, це, мабуть, суперечка або критика: Ваша відповідь неточна. "JIT" не обмежується віртуальною машиною Java , "швидше, але використовує більше пам'яті" є ймовірним ефектом, але не притаманним концепції JIT, і методи часто не збираються під час першого виклику, а через декілька, коли стане зрозуміло, що витрачений час на JIT'ing в цілому вигідний.
zapl

0

JVM фактично виконує етапи компіляції під час виконання з міркувань продуктивності. Це означає, що у Java немає чистого розділення компіляції та виконання. Спочатку робиться так звана статична компіляція з вихідного коду Java в байт-код. Потім цей байт-код передається JVM для виконання. Але виконання байт-коду відбувається повільно, тому JVM вимірює, як часто виконується байт-код, і коли він виявляє "гарячу точку" коду, який запускається дуже часто, він виконує динамічну компіляцію від байт-коду до машинного коду "точки доступу" (hotspot profiler). Тож ефективно сьогодні програми Java управляються машинним кодом.


0

Для поліпшення продуктивності на Java використовується компілятор Just In Time, також відомий як компілятор JIT. Він включений за замовчуванням. Це компіляція, зроблена під час виконання досить раніше. Java популяризувала використання компілятора JIT, включивши його в JVM.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.