Что делает компилятор JIT?

528

Что конкретно делает JIT-компилятор в отличие от не-JIT-компилятора? Может ли кто-то дать краткое и простое для понимания описание?

Михель Боркент
источник
2
Обновленная ссылка
Акаш Нараян
2
Я нашел youtube.com/watch?v=yQ27DjKnxwo полезным.
Адам Зернер

Ответы:

518

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

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

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

Марк Сидаде
источник
16
И в отличие от интерпретируемого кода, он начинает выполнение инструкций байт-кода или виртуальной машины немедленно без задержки, но выполняет команды медленнее, чем машинный язык.
Аарон
3
JIT часто используется с интерпретированным кодом для преобразования его в машинный язык, но да, чисто интерпретируемый код (без какой-либо JITting) работает медленно. Даже Java-байт-код без JITter очень медленный.
Марк Сидаде
48
Однако цель не обязательно должна быть машинным кодом. JRuby имеет JIT-компилятор, который скомпилирует исходный код Ruby в байт-код Java после нескольких вызовов. Затем, после еще одной пары вызовов, включается JIT-компилятор JVM и компилирует байт-код в собственный код.
Йорг Миттаг
4
Стоит отметить, что, как упоминает Йорг, JIT не обязательно вызывается сразу. Часто код будет интерпретироваться до тех пор, пока не будет определено, что он будет стоить JITting. Поскольку JITting может привести к задержкам, может быть быстрее НЕ JIT некоторого кода, если он используется редко, и поэтому быстрый ответ важнее, чем общее время выполнения.
Адам Яскевич
3
@ErikReppen: Если выйдет новая машина, компиляция и оптимизация программы для этой новой машины с использованием обычного компилятора, скорее всего, даст результаты быстрее, чем JIT. С другой стороны, JIT, оптимизированный для этой новой машины, сможет оптимизировать производительность кода, который был опубликован до изобретения этой новой машины .
Суперкат
255

Вначале компилятор отвечал за превращение языка высокого уровня (определяемого как более высокий уровень, чем ассемблер) в объектный код (машинные инструкции), который затем связывался (с помощью компоновщика) в исполняемый файл.

В какой-то момент эволюции языков компиляторы компилируют язык высокого уровня в псевдокод, который затем интерпретируется (интерпретатором) для запуска вашей программы. Это исключило объектный код и исполняемые файлы и позволило переносить эти языки на несколько операционных систем и аппаратных платформ. Паскаль (составленный в P-Code) был одним из первых; Java и C # являются более свежими примерами. В конце концов термин P-Code был заменен байтовым кодом, так как большинство псевдо-операций имеют длину байта.

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

Крейг Трейдер
источник
5
Однако эта фраза «компилятор Just-In-Time (JIT) является функцией интерпретатора времени выполнения» вызывает путаницу; например, - stackoverflow.com/questions/16439512/…
Стивен С.
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, и это также не было полным решением. Сейчас оно определенно нежизнеспособно.)
Стивен С.
69

JIT-как раз вовремя само слово говорит, когда это нужно (по требованию)

Типичный сценарий:

Исходный код полностью конвертируется в машинный код

JIT сценарий:

Исходный код будет преобразован в язык ассемблера, такой как структура [для ex IL (промежуточный язык) для C #, ByteCode для java].

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

Сравнение JIT и Non-JIT:

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

  • Поскольку машинный код будет сгенерирован во время выполнения ... JIT-компилятор будет генерировать машинный код, оптимизированный для работы архитектуры процессора компьютера.

JIT Примеры:

  1. В Java JIT находится в JVM (виртуальная машина Java)
  2. В C # он находится в CLR (Common Language Runtime)
  3. В Android это в DVM (виртуальная машина Dalvik) или ART (Android RunTime) в более новых версиях.
Durai Amuthan.H
источник
7
JIT предлагает некоторые особые преимущества в средах с поддержкой реальных универсальных типов; можно определить универсальный метод, который будет способен генерировать неограниченный диапазон типов, каждый из которых потребует различного машинного кода, но будет иметь код, генерирующий JIT только для типов, которые фактически создаются. Напротив, в C ++ необходимо, чтобы компилятор генерировал код для всех типов, которые программа когда-либо будет использовать.
суперкат
6
JVM не кодирует JIT при первом запуске. Первые несколько раз он интерпретирует байт-код. Затем, если этот код выполняется достаточно часто, он может решить заняться JITting.
ниндзяль
1
Вы говорите, что JIT в Java - это JVM. Однако мы уже предоставляем скомпилированный код в JVM, не так ли? Затем он снова его компилирует?
Корай Тугай
@KorayTugay - мы предоставляем JVM байт-коды, и JVM преобразует часть этого в машинный код по требованию. Таким образом, ресурсы сохраняются.
Durai Amuthan.H
1
В Java JIT не является JVM. Это только часть этого.
Happy
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, что означает, что код компилируется, когда это необходимо, а не до времени выполнения.

Это полезно, потому что компилятор может генерировать код, оптимизированный для вашей конкретной машины. Статический компилятор, как ваш обычный компилятор C, скомпилирует весь код в исполняемый код на машине разработчика. Следовательно, компилятор будет выполнять оптимизацию на основе некоторых предположений. Он может компилироваться медленнее и выполнять больше оптимизаций, поскольку он не замедляет выполнение программы для пользователя.

Брайан Литтл
источник
Почему скомпилированные коды не хранятся где-то на компьютере пользователя, поэтому при следующем запуске приложения JIT больше не придется их перекомпилировать?
Омерфарукдоган
Хорошие наблюдения. Это можно сделать, но будет ли это выгодно, зависит от платформы и использования приложения. Оптимизация 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) отслеживает такие операторы и методы (как было сказано выше) и компилирует такие куски байтового кода в машинный код для повышения производительности.

Другой похожий пример - поиск шаблона с использованием «Регулярного выражения» в списке строк / предложений.

JIT Compiler не компилирует весь код в машинный код. Он компилирует код с похожим шаблоном во время выполнения.

Посмотрите эту документацию Oracle на Understand JIT, чтобы узнать больше.

Anands23
источник
«Нет необходимости снова и снова компилировать байт-код 10 раз, поскольку одна и та же инструкция будет выполняться 10 раз», - а как насчет обычного компилятора? Компилирует ли он этот кусок несколько раз?
TT_
4

У вас есть код, который компилируется в некоторый IL (промежуточный язык). Когда вы запускаете вашу программу, компьютер не понимает этот код. Он понимает только нативный код. Таким образом, 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, он обычно будет выполняться быстрее на компьютере.

Компилятор Just-in-Time поставляется с виртуальной машиной и используется по желанию. Он компилирует байт-код в специфичный для платформы исполняемый код, который выполняется немедленно.

user3459027
источник
2

JIT-компиляция (также динамическая трансляция или компиляция во время выполнения ) - это способ выполнения компьютерного кода, который включает компиляцию во время выполнения программы - во время выполнения - а не перед выполнением .

ИТ-компиляция представляет собой комбинацию двух традиционных подходов к переводу в машинный код - досрочную компиляцию (AOT) и интерпретацию - и сочетает в себе некоторые преимущества и недостатки обоих. JIT-компиляция сочетает в себе скорость скомпилированного кода с гибкостью интерпретации .

Давайте рассмотрим JIT, используемый в JVM,

Например, JIT-компиляторы HotSpot JVM генерируют динамические оптимизации. Другими словами, они принимают решения по оптимизации во время работы приложения 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. Я думаю, что суть в том, что статистика времени выполнения используется для оптимизации.
Эз
Да, но ответ не сформулировал это так. Буквально JIT не оптимизирует самые горячие 20% кода.
Мабрахам
0

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

Венката Сантош Пидури
источник
2
Я бы не стал отвечать на такие вопросы, если вы не предоставите что-то новое / лучшее. Если вы получаете какую-либо реакцию, это, вероятно, отрицательное мнение или критика: ваш ответ неточен. «JIT» не ограничивается виртуальной машиной Java , «скорее, но использует больше памяти» - вероятный эффект, но он не присущ концепции JIT, и методы часто не компилируются при первом вызове, а скорее после нескольких, когда становится ясно, что потраченное время на JIT'ing в целом выгодно.
Запл
0

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

hi.nitish
источник
0

Компилятор Just In Time, также известный как JIT-компилятор, используется для повышения производительности в Java. Это включено по умолчанию. Это компиляция, выполненная во время выполнения, а не раньше. Java популяризировал использование JIT-компилятора, включив его в JVM.

Ганеш Гири
источник