Каковы преимущества компиляции точно в срок по сравнению с опережающей компиляцией? - PullRequest
67 голосов
/ 21 января 2010

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

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

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

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

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


РЕДАКТИРОВАТЬ Чтобы устранить некоторую путаницу, возможно, было бы важно заявить, что я все для промежуточного представления исполняемых файлов. Это имеет много преимуществ (и на самом деле большинство аргументов для Just-in-Time на самом деле являются аргументами для промежуточного представления). Мой вопрос о том, как они должны быть скомпилированы в нативный код.

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

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

Ответы [ 9 ]

34 голосов
/ 21 января 2010
  1. Большая мобильность: результат (байт-код) остается портативный

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

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

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

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

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

14 голосов
/ 24 января 2010

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

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

Скомпилированные исполняемые файлы, выполняемые точно в срок, обычно имеют преимущество в следующих случаях:

  1. Собственные изображения больше, чем их аналог байт-кода;
  2. Собственные изображения должны регенерироваться всякий раз, когда изменяется исходная сборка или одна из ее зависимостей.

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

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

6 голосов
/ 21 января 2010

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

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

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

4 голосов
/ 21 января 2010
  1. Лучшая поддержка отражения. Это может быть сделано в принципе в заранее скомпилированной программе, но на практике это почти никогда не происходит.

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

2 голосов
/ 02 марта 2018

Кажется, что эта идея была реализована на языке дартс:

https://hackernoon.com/why-flutter-uses-dart-dd635a054ebf

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

2 голосов
/ 05 ноября 2016

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

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

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

2 голосов
/ 07 марта 2014

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

1 голос
/ 21 января 2010

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

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

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

0 голосов
/ 12 декабря 2017

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

...