"В чем разница между JIT-компилятором и интерпретатором?"
Проблема: Какие различия существуют между Just-in-Time компилятором и интерпретатором? Также хотел бы узнать, есть ли отличия между JIT компилятором в .NET и Java? Буду признателен за подробное объяснение этих концепций и их сравнений.
5 ответ(ов)
Я всегда замечал, что более абстрактное объяснение может помочь лучше понять.
Представим, что вы хотите спросить всех в Мексике: "Привет. Как дела?" (ваш исходный язык). Сначала вам нужно перевести его на испанский (**родной язык страны). Этот перевод будет звучать как "Hola. Como estas?"
Если вы знаете испанский, вам не нужно делать перевод (родной код / ассемблер). Вы просто спрашиваете: "Hola. Como estas?"
Если вы не знаете испанского, есть три способа справиться с ситуацией.
Первый способ — это взять испанский словарь (**компилятор) и заранее узнать нужные слова до того, как вы пойдете. Возможно, вы поймете, что "Hola. Que tal?" короче на один слог (оптимизация компилятора), и выберете эту фразу. Это называется компиляция языка; вы заранее преобразуете информацию в родной язык.
Второй способ — это заглянуть в испанский словарь, когда вы уже стоите перед первым человеком, и сохранить полученный результат (поиск слов в последний момент). Преимущество этого подхода в том, что вы можете взять словарь на мандаринском и провести тот же эксперимент в Китае, не таская с собой кучу записок с переведёнными фразами (бинарные файлы для разных платформ).
Третий способ — это искать слова, стоя перед каждым человеком. По сути, вы переводите слова для каждого человека отдельно (вы действуете как косвенный переводчик). При этом любое изменение сразу отражается на следующем человеке (вы можете сменить вопрос на "Привет. Какого цвета ваша собака?" без необходимости возвращаться домой и перезапускать процесс — вам не нужно рекомпилировать фразы).
- Предварительный перевод позволяет вам быстрее всего задать вопрос людям (предварительная компиляция); вам не нужно даже брать с собой словарь.
- Перевод, когда вы видите первого человека в каждой стране, почти так же быстр, как и предварительный перевод, но при этом вы можете путешествовать по нескольким странам без необходимости возвращаться домой за словарем — но это требует наличия нескольких словарей с собой (платформенно-независимая среда выполнения).
- Перевод по требованию намного медленнее, но позволяет изменять слова без необходимости возвращения домой (распределённый язык исходного кода).
Интерпретатор генерирует и выполняет инструкции машинного кода по мере необходимости для каждой команды, независимо от того, была ли она выполнена ранее.
JIT-компилятор (Just-In-Time) кэширует инструкции, которые уже были интерпретированы в машинный код, и повторно использует эти нативные инструкции машинного кода, что экономит время и ресурсы, так как не приходится повторно интерпретировать уже интерпретированные команды.
Вопрос о том, является ли исполняющий движок компилятором или интерпретатором, можно очень просто объяснить, рассмотрев, что происходит, если вызвать одну и ту же функцию 1000 раз. Если код внутри исполняющего движка должен будет 1000 раз проверять какое-то конкретное представление кода, то этот исполняющий движок является интерпретатором этого представления. Если же код внутри исполняющего движка будет проверять это представление лишь несколько раз (обычно, но не обязательно, один раз), то он является компилятором или транслятором этого представления. Стоит отметить, что довольно часто исполняющий движок принимает исходный код и преобразует его в другую форму, которая может быть проверена более удобно. Такой исполняющий движок сочетает в себе компилятор или транслятор первой формы с интерпретатором второй формы.
Заметьте, что интерпретаторы очень редко генерируют какую-либо форму машинного кода. Практически единственный случай, когда интерпретатор генерирует машинный код, — это когда оператор должен выполнять какое-то действие, которое действительно нельзя сделать иначе. Например, если интерпретатор BASIC, работающий на 8080, сталкивается с инструкцией "OUT 100,5", он обычно выполняет эту операцию, сохраняя D3 64 C9 (OUT 64h / RET) в три последовательные байта по какому-то фиксированному адресу, загружая A значением 5 и вызывая этот адрес. Технически интерпретатор может генерировать машинный код, но если бы ту же инструкцию OUT пришлось выполнить 500 раз, интерпретатор должен был бы каждый раз заново генерировать машинный код.
tl;dr
Интерпретатор: выполняет только одну инструкцию за раз.
Just-in-time (JIT): обрабатывает блок кода целиком, компилирует его перед выполнением, что предоставляет много возможностей для оптимизации.
JIT-компилятор генерирует бинарный машинный код, переводя блоки исходного кода. В отличие от него, интерпретатор выполняет перевод построчно.
Почему 2 * (i * i) быстрее, чем 2 * i * i в Java?
Графовая база данных для .NET [закрыто]
Почему Java быстрее с использованием JIT, чем при компиляции в машинный код?
Что значит 'synchronized'?
Как объявить массив в одну строку?