Вопрос

В чем разница между JIT-компилятором и CLR?Если вы компилируете свой код в il и CLR запускает этот код, то что делает JIT?Как изменилась JIT-компиляция с добавлением дженериков в CLR?

Это было полезно?

Решение

JIT - это один из аспектов CLR.

В частности, это часть, ответственная за изменение CIL / MSIL (далее именуемого IL), создаваемого компилятором исходного языка (csc.exe например, для Microsoft c #) в машинный код, созданный для текущего процессора (и архитектуру, которую он предоставляет в текущем процессе, например 32/64-битную).Если рассматриваемая сборка была ngen'd, то процесс JIT совершенно не нужен, и среда CLR прекрасно выполнит этот код без него.

Перед использованием метода, который еще не был преобразован из промежуточного представления, ответственность за его преобразование лежит на JIT.
Именно так когда запуск JIT зависит от конкретной реализации и может быть изменен.Однако дизайн среды CLR требует, чтобы JIT выполнялся до того, как соответствующий код выполняется, JVM, напротив, могут свободно интерпретировать код в течение некоторого времени, пока отдельный поток создает представление машинного кода.
"Обычная" среда CLR использует подход к заглушке до JIT где методы by компилируются JIT только по мере их использования.Это предполагает, что начальная заглушка собственного метода является косвенным указанием JIT скомпилировать метод, а затем изменить исходный вызов, чтобы пропустить начальную заглушку.Текущая компактная версия вместо этого компилирует все методы для типа при его загрузке.

Для решения проблемы добавления дженериков.

Это было последнее крупное изменение спецификации IL и JIT с точки зрения ее семантики, в отличие от деталей внутренней реализации.

Было добавлено несколько новых инструкций IL, и было предоставлено больше опций метаданных для инструментирования типов и членов.Ограничения были добавлены и на уровне IL.

Когда JIT компилирует метод, который имеет общие аргументы (явно или неявно через содержащий класс), он может устанавливать разные пути кода (инструкции машинного кода) для каждого используемого типа.На практике JIT использует общую реализацию для всех ссылочных типов, поскольку переменные для них будут иметь одинаковую семантику и занимать одинаковое пространство (IntPtr.Size).

Для каждого типа значения будет сгенерирован определенный код, основной причиной которого является уменьшение / увеличение размера переменных в стеке / куче.Кроме того, при использовании ограниченного кода операции перед вызовом метода многим вызовам для не ссылочных типов не нужно указывать значение для вызова метода (эта оптимизация также используется в не общих случаях).Это также позволяет использовать значение по умолчанию<T> поведение должно быть правильно обработано, а сравнения с null должны быть удалены как no ops (всегда false) при использовании ненулевого типа значения.

Если во время выполнения предпринята попытка создать экземпляр универсального типа с помощью отражения, то параметры типа будут проверены средой выполнения, чтобы убедиться, что они соответствуют любым ограничениям.Это напрямую не влияет на JIT, если только это не используется в системе типов (маловероятно, хотя и возможно).

Другие советы

Вы компилируете свой код в IL, который выполняется и компилируется в машинный код во время выполнения, это то, что называется JIT.

Редактировать, чтобы еще немного конкретизировать ответ (все еще чрезмерно упрощенный):

Когда вы компилируете свой код C # в Visual Studio, он преобразуется в IL, который понимает среда CLR, IL одинаков для всех языков, работающих поверх среды CLR (что позволяет .NET runtime позволяет использовать несколько языков и легко взаимодействовать между ними).

Во время выполнения IL интерпретируется в машинный код (который специфичен для используемой вами архитектуры), а затем выполняется.Этот процесс называется Just In Time compilation или сокращенно JIT.Только необходимый IL преобразуется в машинный код (и только один раз он "кэшируется" после компиляции в машинный код)., как раз вовремя перед его выполнением, отсюда и название JIT.

Вот как это выглядело бы для C#

Код на C # > Компилятор C # > IL > Среда выполнения .NET > JIT- компилятор > Машинный код > Исполнение

И вот как это выглядело бы для VB

Код VB > Компилятор VB > IL > Среда выполнения .NET > JIT- компилятор > Машинный код > Исполнение

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

Как говорит Джон Скит, JIT является частью CLR.По сути, это то, что происходит под капотом:

  1. Ваш исходный код скомпилирован в байтовый код, известный как common intermediate language (CIL).
  2. Метаданные из каждого класса и всех методов (и любой другой вещи: O) включаются в PE-заголовок результирующего исполняемого файла (будь то dll или exe).
  3. Если вы создаете исполняемый файл, заголовок PE также включает обычный загрузчик, который отвечает за загрузку CLR (Common language runtime) при выполнении вашего исполняемого файла.

Теперь, когда вы выполняете:

  1. Загрузчик инициализирует среду CLR (в основном путем загрузки сборки mscorlib) и инструктирует ее выполнить вашу сборку.
  2. Среда CLR выполняет вашу основную запись.
  3. Теперь у классов есть векторная таблица, в которой хранятся адреса функций метода, так что при вызове myMethod выполняется поиск по этой таблице, а затем выполняется соответствующий вызов по адресу.При запуске ВСЕ записи для всех таблиц имеют адрес JIT-компилятора.
  4. Когда выполняется вызов одного из таких методов, JIT вызывается вместо фактического метода и получает управление.Затем JIT компилирует CIL-код в фактический ассемблерный код для соответствующей архитектуры.
  5. Как только код скомпилирован, JIT переходит в таблицу векторов методов и заменяет адрес адресом из скомпилированного кода, так что каждый последующий вызов больше не вызывает JIT.
  6. Наконец, JIT обрабатывает выполнение скомпилированного кода.
  7. Если вы вызываете другой метод, который еще не скомпилирован, вернитесь к 4...и так далее...

JIT - это, по сути, часть из CLR.Сборщик мусора - это другое.Совсем другое дело, где вы распределяете обязанности по взаимодействию и т.д., и я крайне недостаточно квалифицирован для комментариев :)

Я знаю, что тема довольно старая, но я подумал, что мог бы добавить картинку, которая помогла бы мне понять JIT.Это из замечательной книги Среда CLR через C # Джеффри Ритчера.На рисунке метаданные, о которых он говорит, - это метаданные, передаваемые в заголовке сборки, где хранится вся информация о типах в сборке:

JIT image from CLR via C#

1) при компиляции программы .net программный код .net преобразуется в код промежуточного языка (IL)

2) при выполнении программы код промежуточного языка преобразуется в машинный код операционной системы по мере вызова метода;это называется JIT-компиляцией (точно в срок).

  1. Среда выполнения общего языка (CLR) является интерпретатором, в то время как Just In Time (JIT) является компилятором в .Net Framework.

2.JIT - это внутренний компилятор .NET, который берет код MicroSoft Intermediate Code Language (MSICL) из CLR и выполняет его в соответствии с машинными инструкциями, в то время как CLR работает как движок, его основная задача - предоставить JIT код MSICL, чтобы гарантировать, что код полностью скомпилирован в соответствии со спецификацией машины.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top