Компиляция кода.NET или усложнение?

Q1) Почему C# изначально компилируется в IL, а затем во время выполнения JIT соблюдается и запускается поверх виртуальной машины (?). Или это JIT соответствует родному машинному коду?

Q2) Если второе верно (JIT соответствует собственному машинному коду), то где находится песочница.NET, в которой выполняется код?

Q3) Кроме того, почему код компилируется в IL в первую очередь. Почему бы просто не скомпилировать в машинный код все время? Существует инструмент от MS, который называется ngen, но почему это необязательно?

6 ответов

Решение

IL - это JIT'd (JIT = Just In Time), скомпилированный с собственным машинным кодом при запуске процесса.

Использование уровня виртуальной машины позволяет.NET вести себя согласованно на разных платформах (например, int всегда 32-битный независимо от того, работаете ли вы на 32- или 64-битной машине, это не относится к C++).

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

A1) JIT компилируется в машинный код

А2) В.net нет такого термина как песочница. Вместо этого есть AppDomains. И они запускаются как часть CLR (т.е. как часть исполняемого процесса)

A3) Недостатки NGen от Джеффри Рихтера:

  • NGen'd файлы могут выйти из синхронизации. Когда CLR загружает файл NGen'd, он сравнивает ряд характеристик о ранее скомпилированном коде и текущей среде выполнения. Если какие-либо характеристики не совпадают, файл NGen'd не может быть использован, и вместо него используется обычный процесс JIT-компилятора.

  • Низкая производительность по времени загрузки (перебазирование / связывание). Файлы сборки - это стандартные файлы Windows PE, и каждый из них содержит предпочтительный базовый адрес. Многие разработчики Windows знакомы с проблемами, связанными с базовыми адресами и перебазированием. Когда JIT компилирует код, эти проблемы не имеют значения, потому что правильные ссылки на адреса памяти вычисляются во время выполнения.

  • Низкая производительность во время исполнения. При компиляции кода NGen не может сделать столько предположений о среде исполнения, сколько компилятор JIT может. Это приводит к тому, что NGen.exe создает худший код. Например, NGen не оптимизирует использование определенных инструкций процессора; он добавляет косвенные ссылки для доступа к статическим полям, потому что фактический адрес статических полей не известен до времени выполнения. NGen вставляет код для вызова конструкторов классов везде, потому что он не знает порядок, в котором будет выполняться код, и если конструктор класса уже был вызван.

Вы можете использовать NGEN для создания собственных версий ваших сборок.NET. Это означает, что JIT не должен делать это во время выполнения.

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

Код.NET компилируется в IL для совместимости. Поскольку вы можете создавать код с использованием C#, VB.NET и т. Д., JIT необходим общий набор команд (IL) для компиляции в собственный код. Если JIT должен был знать о языках, то JIT нужно будет обновлять при выпуске нового языка.NET.

Я не уверен насчет вопроса о песочнице, я думаю, что приложение.NET работает с 3 доменами приложений. Один домен содержит среды выполнения.NET (mscorlib, system.dll и т. Д.), Другой домен содержит ваш код.NET, и я не могу вспомнить, для чего предназначен другой домен. Проверьте http://my.safaribooksonline.com/9780321584090

Скомпилированный код.Net становится IL, который является промежуточным языком точно так же, как и код объекта Javas. Да, можно генерировать машинный код с помощью инструмента NGen. NGen связывает результирующий собственный образ с машиной, поэтому копирование двоичного файла ngen в другую систему не даст ожидаемых результатов. Компиляция в промежуточный код позволяет принимать решения, которые могут быть приняты во время выполнения, которые иначе (легко) не могут быть приняты с помощью языка со статической типизацией, такого как C++, это также позволяет функционировать кодом на различных аппаратных архетектурах, потому что код становится описательным в ощущение, что он также описывает намерение того, что должно происходить в битовом (например, 32 или 64)-агностическом смысле, в отличие от машинно-специфичного кода, который работает только в 32-битных или 64-битных системах, но не в обоих.

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

1. C# скомпилирован в CIL (или IL), потому что он разделяет платформу с остальными языками.NET (именно поэтому вы можете написать DLL на C# и использовать ее в VB.NET или F# без проблем). Затем CLR JIT скомпилирует код в машинный код.

.NET также может работать на нескольких платформах (Mono на *NIX и OS X). Если C# скомпилирован в нативный код, это будет не так просто.

2. Песочницы нет.

3. Охвачено в ответе на #1

A1) Таким образом, он не зависит от платформы (Windows, Linux, Mac) и может также использовать определенные оптимизации для вашего текущего оборудования. Когда JIT скомпилируется, он превращается в машинный код.

A2) Вся инфраструктура (.NET Framework) - это все песочница, поэтому все вызовы, которые вы можете сделать через свое приложение, будут проходить через песочницу.NET Framework.

A3) Как и в ответе 1, он позволяет двоичному файлу.NET работать на разных платформах и выполнять определенные оптимизации на клиентском компьютере на лету.

Другие вопросы по тегам