Як працює Chrome V8? І чому JavaScript в першу чергу не був компільований JIT?


19

Я досліджував перекладачів / укладачів, потім натрапив на JIT-Compilation - зокрема V8 Javascript Engine Google Chrome.

Мої запитання -

  1. Як це може бути швидше, ніж стандартне тлумачення?
  2. Чому JIT-Compilation не використовувався в першу чергу?


Моє поточне розуміння

  1. Кожна програма Javascript запускається як вихідний код , потім, незалежно від способу виконання, в кінцевому підсумку переводиться на машинний код .
    І JIT-Компіляція, і Інтерпретація повинні йти цим шляхом, так як же JIT-Компіляція може бути швидшою (також тому, що JIT обмежений часом, на відміну від AOT-Compilation)?

  2. Здається, що JIT-Compilation є відносно старим нововведенням , заснованим на статті про JIT-компіляцію у Вікіпедії .

"Найперший опублікований компілятор JIT, як правило, відноситься до роботи над LISP Маккарті в 1960 році ."

"Smalltalk (c. 1983 ) запровадив нові аспекти компіляції JIT. Наприклад, переклад на машинний код робився на вимогу, а результат був кешований для подальшого використання. Коли пам'ять стала дефіцитною, система видалила б частину цього коду та відновила це коли воно знову було потрібно ».

То чому для початку було інтерпретовано Javascript ?


Я дуже розгублений, і я провів багато досліджень з цього приводу, але не знайшов задовільних відповідей.

Тож чіткі, стислі відповіді були б вдячні. І якщо потрібно подати додаткові пояснення щодо перекладачів, JIT-компіляторів тощо, це також оцінено.


2
№2 і №3 відповідають, але "Як працює двигун Chrome V8?" без будь-якої кваліфікації занадто широка; Єдина правильна відповідь - посилання на вихідний код V8. Ви мали на увазі запитати щось більш конкретне про V8? (якщо ні, то найкраще видалити цю частину питання)
Іксрек,

По-друге, єдиним моїм запитанням №1 було зрозуміти №2, тому я його видалю. Дякуємо за вклад.
Антон Парась

Це не згадується в інших відповідях, але складання JIT важко. Це зробити непросто, тому що помилки, що виникають в результаті компіляції JIT, призводять до segfault замість помилок - програма виходить з ладу замість того, щоб кидати помилку в консолі. Так, для грамотного програміста C, комфортного для 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, можна побачити в Invoking Applet Methods From JavaScript Code . Також через JavaScript можна було йти іншим способом виклику коду JavaScript з аплету .

Початковий намір JavaScript полягав у тому, щоб зв’язати аплети та HTML-сторінки, що їх містять. Для такої невеликої задачі не потрібно великої продуктивності (якщо ви хотіли продуктивності, скористайтеся методом аплета, який є JIT'ed).

Лише після того, як 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
caub

Так. І чомусь дивно, коли я вказав на те, що вище, я прийняв рішення про це!
quick_now

1

JIT швидкі для JavaScript, тому що неможливо генерувати швидкий машинний код, коли ви не знаєте тип своїх змінних.

Коли у вас немає інформації про тип, обчислення коштують дорого. Наприклад,

x + y

є досить складним, якщо ви нічого не знаєте про x і y. Це можуть бути цілі числа, парні, рядки або навіть об'єкти, де цей обчислення має побічні ефекти. Оскільки у нас немає статичного набору тексту, це дорогий розрахунок.

За допомогою щойно вкладеної компіляції ми можемо використовувати інформацію про час виконання та перетворити це на швидше обчислення. Під час виконання V8 відстежує тип змінних. Якщо вищевказаний код виконується кілька разів з, скажімо, рядків, компілятор може виконати набагато простіші інструкції для об'єднання рядків. Отже, коли компілятор досягає x + yзамість того, щоб виконувати багато коду, який розгалужується на багато різних типів x і y, компілятор швидко перевіряє, чи є у нас рядки, а потім виконує лише кілька рядків машинного коду, які конкретно об'єднують рядки.

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


0

1) Як це може бути швидше, ніж стандартне тлумачення? Що ж, продуманий приклад був би наступним; припустимо, у нас є 2 програми ApplicationCompiled та ApplicationInterpreted. Обидві ці програми роблять абсолютно одне і те ж і поділяють один і той же вихідний код. ApplicationCompiled займає 6 секунд для складання.

Скажімо, що терміни сценарію A такі:

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

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

Очевидно, що це дуже спрощено, але така ж ідея може бути застосована до компіляції / інтерпретації JIT. Наступним питанням буде таке: "як ми визначимось - з низькою вартістю - якщо ця галузь повинна бути складена або інтерпретована JIT"? Я тут зі своєї ліги :)

2) Чому JIT-Compilation не використовувався в першу чергу? Не знаю, але я усвідомлюю, що це просто питання ресурсів та зрілості наявного прогресу в створенні важко оптимізованої мови, як-от JavaScript застосовує такі методи вдосконалення, як ця. Нижчих висячих фруктів у той час було, мабуть, багато.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.