Подтвердить что ты не робот

В чем преимущества компиляции "точно вовремя" против компиляции в будущем?

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

Итак, это основные аргументы компиляции pro-JIT, которые я обычно слышу:

  • Компиляция "точно в срок" обеспечивает большую переносимость. Не относится ли это к промежуточному формату? Я имею в виду, ничто не мешает вам скомпилировать ваш виртуальный байт-код в собственный байт-код, как только вы его получите на своей машине. Переносимость является проблемой на фазе "распределения", а не во время "запуска".
  • Хорошо, тогда как насчет генерации кода во время выполнения? Ну, то же самое. Ничто не мешает вам интегрировать компилятор "точно в срок" для реальной потребности в срочном порядке в вашей родной программе.
  • Но среда выполнения компилирует его в собственный код только один раз в любом случае и сохраняет полученный исполняемый файл в каком-то кеше где-то на вашем жестком диске. Да, конечно. Но он оптимизировал вашу программу по временным ограничениям, и это не улучшило ее. См. Следующий параграф.

Не похоже, что компиляция впереди не имела преимуществ. Компиляция имеет ограничения по времени: вы не можете держать конечного пользователя в ожидании, пока ваша программа запускается, поэтому у нее есть компромисс, который можно сделать где-то. Большую часть времени они просто оптимизируют меньше. У моего друга были профилирующие доказательства того, что встроенные функции и развертки циклов "вручную" (обфускация исходного кода в процессе) оказали положительное влияние на производительность в его программе С# с номером-хрустом; делая то же самое на моей стороне, с моей программой C, заполняющей ту же задачу, не давшей положительных результатов, и я считаю, что это связано с обширными преобразованиями, которые мой компилятор разрешил сделать.

И все же нас окружают джитт-программы. С# и Java, скрипты Python могут компилироваться в какой-то байт-код, и я уверен, что целая куча других языков программирования делает то же самое. Должна быть веская причина, по которой мне не хватает. Итак, что делает компиляцию точно в срок настолько превосходящей компиляцию впереди?


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

Большинство runtimes (или компиляторы, если на то пошло) предпочитают либо компилировать их точно или вовремя. Поскольку компиляция впереди выглядит как лучшая альтернатива мне, потому что у компилятора больше времени для выполнения оптимизации, мне интересно, почему Microsoft, Sun и все остальные идут наоборот. Я немного сомневаюсь в оптимизации профилирования, так как мой опыт работы с точно в срок скомпилированными программами отображал слабые базовые оптимизации.

Я использовал пример с кодом C только потому, что мне нужен пример компиляции впереди по сравнению с точно в срок. Тот факт, что код C не был передан промежуточному представлению, не имеет отношения к ситуации, так как мне просто нужно было показать, что компиляция впереди может дать лучшие немедленные результаты.

4b9b3361

Ответ 1

Страница ngen пролила beans (или, по крайней мере, обеспечила хорошее сравнение собственных изображений и JIT-скомпилированных изображений). Ниже приведен список преимуществ исполняемых файлов, которые компилируются заранее:

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

И вот список преимуществ исполняемых исполняемых файлов "точно в срок":

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

И общие соображения Microsoft по этому вопросу:

  • Большие приложения обычно выигрывают от компиляции досрочно, а для небольших - вообще нет;
  • Любой вызов функции, загружаемой из динамической библиотеки, требует накладных расходов одной дополнительной команды перехода для исправлений.

Необходимость регенерации изображения, которое выполняется заранее, каждый раз, когда один из его компонентов является огромным недостатком для собственных изображений. Это корень проблемы хрупкого базового класса. Например, в С++, если макет класса из DLL, который вы используете с вашим родным приложением, изменяется, вы ввернуты. Если вы программируете вместо интерфейсов, вы по-прежнему ввернуты, если интерфейс изменится. Если вместо этого вы используете более динамический язык (скажем, Objective-C), вы в порядке, но это связано с поражением производительности.

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

Ответ 2

  • Большая мобильность: конечный (байт-код) остается портативный

  • В то же время, больше зависит от платформы: поскольку Компиляция JIT происходит на то же самое, что код работает, он может быть очень, очень точно настроен для этой конкретной системы. Если вы это сделаете скорейшее компиляция (и все еще хотите отправить один и тот же пакет все), вы должны идти на компромисс.

  • Усовершенствования в технологии компилятора могут повлиять на существующих программ. Лучше C компилятор вообще не помогает с уже развернутыми программами. лучший JIT-компилятор улучшит выполнение существующих программ. Код Java, который вы написали десять лет назад, будет работать быстрее сегодня.

  • Адаптация к меткам времени выполнения. JIT-компилятор может не только смотреть на кода и целевой системы, но также о том, как используется код. Оно может измерить текущий код и принимать решения о том, как оптимизировать согласно, например, что значения параметров метода обычно случается.

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

Я полагаю, что где-нибудь можно было сохранить результат компиляции JIT, чтобы его можно было повторно использовать в следующий раз. Это даст вам "опережающую" компиляцию для второго запуска программы. Может быть, умные люди в Sun и Microsoft считают, что свежий JIT уже достаточно хорош, и лишняя сложность не стоит того, чтобы справиться с проблемой.

Ответ 3

Простая логика подсказывает, что компиляция огромной программы размера MS Office даже из байт-кодов займет слишком много времени. У вас будет огромное время пуска, и это напугает любого из вашего продукта. Конечно, вы можете прекомпилировать во время установки, но это также имеет последствия.

Другая причина заключается в том, что не все части приложения будут использоваться. JIT будет компилировать только те части, которые заботятся о пользователях, оставляя потенциально 80% кода нетронутым, экономя время и память.

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

Ответ 4

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

  • Оптимизации, которые часто можно определить только путем динамического наблюдения за программой. Например, встраивание виртуальных функций, анализ эвакуации, чтобы включить распределение стека в распределения кучи и блокировать укрупнение.

Ответ 5

Одно из преимуществ JIT, которое я не вижу здесь, - это возможность встроить/оптимизировать отдельные сборки /dlls/jars (для простоты я просто собираюсь использовать "сборки" здесь).

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

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

Ответ 6

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

Те дни давно прошли. При использовании языка сценариев, такого как PHP или JavaScript, вы можете немедленно протестировать любые изменения. Это не тот случай с Java, хотя appservers дают вам горячее развертывание. Поэтому очень удобно, что Java-программы могут быть скомпилированы быстро, поскольку компиляторы байт-кода довольно просты.

Но нет таких вещей, как JIT-языки. Вперед компиляторы были доступны для Java в течение некоторого времени, а в последнее время Моно представил его CLR. Фактически, MonoTouch вообще возможно из-за компиляции AOT, поскольку неродные приложения запрещены в Магазин приложений Apple.

Ответ 7

Я тоже пытался понять это, потому что увидел, что Google движется к замене своей виртуальной машины Dalvik (по существу другой виртуальной машины Java, такой как HotSpot) с Android Run Time (ART), которая является компилятором AOT, но Java обычно использует HotSpot, который является JIT-компилятором. По-видимому, ARM ~ 2x быстрее, чем Dalvik... поэтому я подумал: "Почему Java не использует AOT?". В любом случае, из того, что я могу собрать, основное различие заключается в том, что JIT использует адаптивную оптимизацию во время выполнения, которая (например) позволяет ТОЛЬКО те части байт-кода, которые выполняются часто, чтобы скомпилироваться в собственный код; тогда как AOT компилирует весь исходный код в собственный код, а код меньшей суммы работает быстрее, чем код большего количества.
Я должен вообразить, что большинство приложений для Android состоит из небольшого количества кода, поэтому в среднем имеет смысл скомпилировать весь исходный код с помощью собственного кода AOT и избежать накладных расходов, связанных с интерпретацией/оптимизацией.

Ответ 8

Разница между платформой-браузером-динамиком и платформенным браузером заключается в том, как будет скомпилировано приложение angular. Использование динамической платформы делает angular отправкой компилятора "Just-in-Time" как в интерфейсе, так и в вашем приложении. Это означает, что ваше приложение компилируется на стороне клиента. С другой стороны, использование платформы-браузера приводит к тому, что предварительно скомпилированная версия вашего приложения будет отправлена ​​в браузер. Обычно это означает, что в браузер отправляется значительно меньший пакет. angular2 -документация для начальной загрузки https://angular.io/docs/ts/latest/guide/ngmodule.html#!#bootstrap объясняет это более подробно.