Как работает Chrome V8? И почему JavaScript не был JIT-компилированным?

19

Я изучал интерпретаторы / компиляторы, а потом наткнулся на JIT-компиляцию - в частности, на Google Chrome V8 Javascript Engine.

Мои вопросы -

  1. Как это может быть быстрее, чем стандартная интерпретация?
  2. Почему JIT-Compilation не использовался в первую очередь?


Мое текущее понимание

  1. Каждая программа Javascript начинается с исходного кода , а затем, независимо от способа выполнения, в конечном итоге переводится в машинный код .
    И JIT-компиляции и интерпретации должны идти по этому пути, так как может JIT-компиляции будет быстрее (и потому , что JIT время ограниченным, в отличие от АОТ-компиляции)?

  2. Похоже, что JIT-компиляция является относительно старой инновацией , основанной на статье JIT-компиляции Википедии .

«Самый ранний опубликованный JIT-компилятор обычно приписывают работе над LISP Маккарти в 1960 году ».

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

Так почему же Javascript интерпретируется с самого начала ?


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

Так что четкие, краткие ответы будут оценены. И если необходимо получить дополнительное объяснение о интерпретаторах, JIT-компиляторах и т. Д., Это также приветствуется.

Антон Парас
источник
2
Ответы № 2 и № 3, но «Как работает Chrome V8 Engine?» без какой-либо квалификации слишком широк; единственный правильный ответ - ссылка на исходный код V8. Вы хотели спросить что-то более конкретное о V8? (если нет, то было бы лучше удалить эту часть вопроса)
Ixrec
На второй взгляд, единственное, что я хотел спросить # 1, это понять # 2, поэтому я его уберу. Спасибо за вклад.
Антон Парас
Это не упоминается в других ответах, но компиляция JIT трудна. Это непросто, потому что ошибки, возникающие в результате JIT-компиляции, приводят к ошибкам сегмента, а не к ошибкам - программа вылетает, а не выдает ошибку в консоли. Да, для компетентного программиста на Си, комфортного с GDB, это не проблема. Но почти всем компетентным программистам на C, которые знакомы с gdb, платят за работу над другими проектами Некоторые другие языки, такие как Perl и Ruby, до сих пор не имеют основных интерпретаторов JIT.
Slebetman
На случай, если вам интересно. Я говорю об этом с точки зрения основного разработчика / сопровождающего для языка программирования. В течение нескольких лет меня нанимали на язык программирования Ferite. Одним из пожеланий, которые у нас были, было внедрение JIT. Этого никогда не было - вместо этого мы переехали. PHP только недавно получил JIT-компилятор (HVVM) благодаря тому, что Facebook вложил в него достаточно денег, чтобы это произошло.
Slebetman

Ответы:

43

Короткий ответ заключается в том, что JIT имеет более длительное время инициализации, но намного быстрее в долгосрочной перспективе, а JavaScript изначально не предназначался для долгосрочной работы.

В 90-х годах типичный JavaScript на веб-сайте будет состоять из одной или двух функций в заголовке и небольшого количества кода, встроенного непосредственно в onclickсвойства и тому подобное. Обычно он запускается правильно, когда пользователь ожидает огромную задержку загрузки страницы. Подумайте об очень простой форме проверки или крошечные математические утилиты, такие как калькуляторы процентов по ипотечным кредитам

Интерпретация по мере необходимости была намного проще и обеспечивала совершенно адекватную производительность для случаев использования дня. Если вы хотели что-то с долговременной производительностью, вы использовали flash или java-апплет.

Карты Google в 2004 году были одним из первых приложений-убийц для интенсивного использования JavaScript. Он открывал глаза на возможности JavaScript, но также подчеркивал его проблемы с производительностью. Google потратил некоторое время, пытаясь побудить браузеры повысить производительность JavaScript, а затем решил, что конкуренция будет лучшим мотиватором, а также предоставит им лучшее место за столом стандартов браузера. В результате Chrome и V8 были выпущены в 2008 году. Теперь, спустя 11 лет после появления Google Maps, у нас появились новые разработчики, которые не помнят, чтобы JavaScript когда-либо считался неадекватным для такого рода задач.

Скажем, у вас есть функция animateDraggedMap. Для его интерпретации может потребоваться 500 мс, а для компиляции JIT - 700 мс. Однако после JIT-компиляции для выполнения может потребоваться всего 100 мс. Если это 90-е годы, и вы вызываете функцию только один раз, а затем перезагружаете страницу, JIT не стоит этого вообще. Если сегодня и вы звоните animateDraggedMapсотни или тысячи раз, то дополнительные 200 мс при инициализации - ничто, и это может быть сделано за кулисами, прежде чем пользователь даже попытается перетащить карту.

Карл Билефельдт
источник
2

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

Об этом можно сказать немало - это предмет значительных исследований. Мое собственное объяснение здесь состоит в том, что я начал писать бледно по сравнению с ответом, данным в разделе «Понимание различий»: традиционный интерпретатор, JIT-компилятор, JIT-интерпретатор и AOT-компилятор


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

Первоначальная цель Java Script заключалась в том, чтобы ссылаться на Java-апплеты на веб-странице. Возможность щелкнуть по какой-либо кнопке или ввести значение в поле формы, а затем выполнить работу в методе Java-апплета, можно увидеть в разделе «Вызов методов апплета из кода JavaScript» . С помощью JavaScript также можно было пойти другим путем, вызывая код JavaScript из апплета .

Первоначальная цель JavaScript состояла в том, чтобы связать апплеты и HTML-страницы, которые их содержали. Для такой небольшой задачи не требуется высокая производительность (если вам нужна производительность, вызовите метод апплета, который является JIT).

Только после того, как Netscape начал выполнять значительную работу с JavaScript как своим собственным языком и продвигать его для разработки (включая JavaScript на стороне сервера в Netscape Enterprise Server - который, кстати, выполнил предварительную компиляцию), JavaScript стал серьезной целью. , После этого потребовалось много лет, чтобы необходимые инструменты сделали его полезным.

Сообщество
источник
1
Нет, Javascript не связан с Java. А Java-апплеты - это байт-код JVM.
Василий Старынкевич
@BasileStarynkevitch JavaScript был разработан для работы с Java-апплетами на страницах деревушки, выступая в качестве связующего звена между html dom и методами, содержащимися в объектах Java. Он не был и никогда не был предназначен для Java.
JavaScript изначально назывался ECMAScript (или что-то в этом роде) и не имел ничего общего с Java. Как он должен называться JavaScript, является предметом отдельного исследования для заинтересованных. Это вызвало путаницу с самого начала.
quick_now
1
@quickly_now и до сих пор tc39.github.io/ecma262
совещание
Да. И по какой-то странной причине, когда я указал на это выше, мне за это проголосовали!
quick_now
1

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

Когда у вас нет информации о типе, вычисления стоят дорого. Например,

x + y

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

Благодаря своевременной компиляции мы можем использовать информацию времени выполнения и превратить ее в более быстрые вычисления. Во время выполнения V8 отслеживает тип переменных. Если приведенный выше код выполняется несколько раз, скажем, со строками, компилятор может выполнить гораздо более простые инструкции для конкатенации строк. Таким образом, когда компилятор достигает x + y, вместо того, чтобы запускать много кода, который разветвляется для множества различных типов x и y, компилятор быстро проверяет, есть ли у нас снова строки, а затем выполняет всего несколько строк машинного кода, который специально объединяет строки.

Например, в C ++ компилятор знает типы x и y заранее, так как мы должны были объявить переменные. Таким образом, он может генерировать оптимизированный машинный код для объединения строк перед тем, как запускать код.

user835611
источник
0

1) Как это может быть быстрее, чем стандартная интерпретация? Хорошо, придуманный пример будет следующим; Предположим, у нас есть 2 приложения ApplicationCompiled и ApplicationInterpreted. Обе эти программы делают одно и то же и используют один и тот же исходный код. Компиляция ApplicationCompiled занимает 6 секунд.

Предположим, что время сценария А:

  • Для приложения скомпилировано: 4 секунды
  • Для ApplicationInterpreted: 12 секунд

Таким образом, в общей сложности ApplicationCompiled требуется 10 секунд для запуска сценария A (6 секунд компиляции, 4 секунды запуска), а ApplicationInterpreted - 12 секунд для запуска. У меня нет конкретного примера, чтобы показать вам, и я не уверен, в каких случаях вышеприведенное будет верным - это также сильно зависит от того, насколько интеллектуальны интерпретатор и компилятор.

Очевидно, что это очень упрощено, но, тем не менее, эту же идею можно применить к JIT-компиляции / интерпретации. Тогда следующий вопрос будет: «Как мы определим - с низкой стоимостью - должна ли эта ветка компилироваться или интерпретироваться JIT»? Я вне моей лиги здесь :)

2) Почему JIT-Compilation не использовался в первую очередь? Не знаю, но я повторяю, что это просто вопрос ресурсов и зрелости имеющегося прогресса в создании трудно оптимизируемого языка, такого как JavaScript, для применения таких технологий. В то время, вероятно, было много висящих фруктов.

cwap
источник