Движок JavaScript: что внутри. Разберёмся, как работает движок V8 и… | by Андрей Шагин | NOP::Nuances of Programming
Чтобы разобраться в том, как работает механизм обработки кода (иначе говоря, движок JavaScript), надо понять, что происходит при выполнении кода. Такие знания помогают программистам писать лучший, более быстрый и умный код.
Движки JavaScript — это не что иное, как программы, преобразующие код на JavaScript в код более низкого уровня, который компьютер сможет понять. Эти движки встроены в браузеры и веб-серверы (Node.js), что даёт возможность выполнять код и осуществлять компиляцию во время выполнения.
Разве JavaScript — это не интерпретируемый язык?
Краткий ответ: это зависит от реализации. Обычно JavaScript относят к интерпретируемым языкам, хотя вообще-то он компилируется. Современные компиляторы JavaScript фактически выполняют JIT-компиляцию, т.е. компиляцию «на лету», которая осуществляется во время работы программы.
Существует множество разных движков. У каждого из них внутри есть что-то вроде конвейера с интерпретатором и конвейера с оптимизатором и компилятором. Интерпретатор генерирует байт-код, а оптимизатор выдаёт оптимизированный машинный код. Далее в статье в качестве примера будет использоваться движок V8.
V8 — это высокопроизводительный движок от Google с открытым исходным кодом JavaScript и WebAssembly, написанный на языке C++.Он используется в Chrome, Node.js и других платформах и реализует ECMAScript и WebAssembly (см.v8.dev).
Всякий раз, когда JavaScript-код отправляется в движок V8, он проходит ряд этапов для отображения console.log:
Парсер
Движок выполняет то, что мы называем лексическим анализом. Это первое, что происходит с файлом JavaScript при попадании в движок. Код разбивается на части, называемые токенами, для выявления их назначения, после чего мы узнаём, что код пытается сделать.
Абстрактное синтаксическое дерево (AST)
На основе этих токенов создаётся то, что мы называем AST. Синтаксическое дерево — это древовидное представление синтаксической структуры кода JavaScript, и мы можем использовать этот инструмент для анализа преобразования кода AST.
Интерпретатор
Интерпретатор читает файлы JavaScript построчно и преобразовывает их на ходу (во время работы программы, не прерывая её выполнение). На основе сгенерированного кода AST интерпретатор начинает быстро создавать байт-код. Никаких оптимизаций здесь не выполняется, так что байт-код этот неоптимизированный.
Байт-код не является таким низкоуровневым, как машинный код, но всё же может быть интерпретирован движком JavaScript для выполнения кода.
Профайлер
Профайлер отвечает за проверку кода. Он вызывает специальное средство контроля, которое отслеживает код и наблюдает за ходом его выполнения, обращая наше внимание на то, как можно оптимизировать код. Выдаёт, например, информацию о том, сколько раз код запускался, какие типы используются и как мы можем его оптимизировать?
Так что, если профайлер находит часть кода, которую можно оптимизировать, он передаёт этот код JIT-компилятору, чтобы он мог быть скомпилирован и выполнялся быстрее. Рассмотрим эти конвейеры с интерпретатором и компилятором более подробно.
Оптимизирующий компилятор
Задача оптимизирующего компилятора — определить, что делает программа, подлежащая оптимизации, и создать из неё оптимизированную программу, выполняющую всё то же самое, только быстрее.
Он не преобразует файлы на лету. Он делает свою работу заранее, создавая преобразование только что написанного кода и компилируя его в язык, понятный для компьютера.
Деоптимизация
Оптимизирующий компилятор на основе имеющихся у него данных профилирования делает определённые предположения, а затем выдаёт высокооптимизированный машинный код. Но вполне возможно, что в какой-то момент одно из предположений окажется неверным. И тогда оптимизирующий компилятор может деоптимизировать код.
JavaScript — это динамический язык программирования, а это подразумевает, что свойства могут легко добавляться или удаляться из объекта после его создания. Для написания более лучшего кода надо понимать, как JavaScript определяет объекты и как движок работает с объектами и свойствами.
Enumerable → определяет, перечисляется ли свойство в циклах for—in.
Value → само значение.
Writable → определяет, можно ли свойство изменить.
Configurable → определяет, можно ли удалить свойство.
Оптимизация доступа к свойству
В динамических языках, таких как JavaScript, для доступа к свойствам требуется ряд инструкций. Поэтому почти в каждом движке имеется оптимизация для ускорения этого доступа. Такая оптимизация в V8 реализуется скрытыми классами: V8 присоединяет скрытый класс к каждому отдельному объекту. Целью скрытых классов является оптимизация времени доступа к свойствам.
Скрытые классы работают аналогично фиксированным макетам (классам) объектов, используемым в таких языках, как Java (за исключением того, что они создаются во время выполнения). Магия здесь в том, что несколько объектов могут иметь один и тот же скрытый класс, поэтому необходимы только минимальные ресурсы, а код становится быстрее:
Выгода становится очевидной, когда объектов много. Ведь пока у них один и тот же скрытый класс, информацию приходится сохранять только один раз независимо от того, сколько всего имеется объектов!
Тема оптимизации очень обширна и может стать предметом обсуждения отдельной статьи.
Цель встроенного кэширования в том, чтобы ускорить привязку метода времени выполнения. Происходит это за счёт запоминания результатов поиска предыдущего метода непосредственно в месте вызова.Встроенное кэширование особенно полезно для динамически типизированных языков, где большинство, если не все привязки методов происходят во время выполнения и где виртуальные таблицы методов часто не могут быть использованы.
Основная причина существования скрытых классов — концепция встроенных кэшей. Движки JavaScript используют встроенные кэши для запоминания информации о том, где найти свойства в объектах. Поэтому нет необходимости повторять дорогостоящий поиск свойств при каждом доступе к ним. Зачем каждый раз искать свойства, когда со встроенными кэшами это значительно быстрее?
инициализировать объекты лучше всегда одним и тем же способом, чтобы скрытые классы у них не были разными;
с атрибутами свойств элементов массива надо быть осторожным, чтобы они могли аккуратно сохраняться, а работа с ними была эффективной.
Читайте также:
Как работает новый await верхнего уровня в JavaScript
Чистый код JavaScript — Вертикальное форматирование
Что значит this в JavaSсript?
Читайте нас в телеграмме, vk и Яндекс.Дзен
Перевод статьи Leonardo Freitas: Inside the JavaScript Engine
Почти всё там изложенное я уже успел узнать сам из разных источников.
Рассказано, что движок JavaScript «V8» встроен в браузер «Google Chrome» и отвечает там за выполнение скриптов на языке JavaScript. Движок JavaScript «V8» не зависит от программы (изначально браузера), в которую он встроен. Поэтому стало возможным появление среды выполнения «Node.js», которая тоже использует этот движок.
Область применения среды выполнения «Node.js» огромна. В частности, благодаря движку JavaScript «V8», среду выполнения «Node.js» можно использовать для написания обычных приложений для настольного компьютера (по-английски «desktop applications» или «desktop apps») с помощью таких проектов, как фреймворк «Electron».
С помощью фреймворка «Electron» создан, к примеру, очень популярный сейчас редактор кода «Visual Studio Code».
Другие браузеры используют их собственные движки JavaScript. Например:
– браузер «Mozilla Firefox» использует движок JavaScript «SpiderMonkey»: https://spidermonkey.dev
– браузер «Safari» (разработанный компанией «Apple») использует движок JavaScript «JavaScriptCore» (также его называют «Nitro»): https://developer.apple.com/documentation/javascriptcore
– браузер «Microsoft Edge» первоначально использовал движок JavaScript «Chakra»: https://github.com/chakra-core/ChakraCore
Но сейчас браузер «Microsoft Edge» перестроен для работы на базе браузера «Chromium» и поэтому стал использовать движок JavaScript «V8».
Кроме перечисленных существуют и другие движки JavaScript.
Движок JavaScript «V8» написан на языке программирования «C++» и постоянно улучшается. Он портирован для работы в операционных системах «macOS», «Windows», «Linux» и некоторых других. Детали реализации этого движка можно найти на его официальном сайте:
https://v8.dev
Все движки JavaScript участвуют в гонке за производительностью (скоростью работы). Изначально язык программирования JavaScript считался интерпретируемым языком программирования, но сейчас это не так: современные движки компилируют код.
Ускорение работы движка дало программистам возможность увеличить размер программ, написанных на языке JavaScript, с нескольких десятков строк кода до полноценных приложений, включающих от тысяч до сотен тысяч строк кода.
Tags: Инструмент, Образование, Программирование
Subscribe
Git for Windows: вклад в проект с помощью патча, часть 3
Начало: 1. Git for Windows: вклад в проект с помощью патча, часть 1 2. Git for Windows: вклад в проект с помощью патча, часть 2 Ранее я описал,…
Git for Windows: вклад в проект с помощью патча, часть 2
Начало: « Git for Windows: вклад в проект с помощью патча, часть 1». В предыдущем посте я теоретически описал разные способы вклада в проект, в том…
Git for Windows: вклад в проект с помощью патча, часть 1
В этом посте подразумевается работа в операционной системе «Windows 10». Я использую программу «Git» (точнее, ее дистрибутив «Git for Windows»)…
Photo
Hint http://pics.livejournal.com/igrick/pic/000r1edq
0 comments
0 comments
Блог · V8
Блог · V8
Сжатие указателя в Oilpan Внутренние память CPPGC
Отключение постов в блоге .
Ускоренная инициализация экземпляров с новыми функциями класса Внутреннее устройство
Выпуск V8 v9.9 Выпуск
Библиотека Oilpan Внутренние память CPPGC
V8 Release V9.7 Выпуск
Webassembly Dynamic Tiering Lateing to Trok in Chrome 96
Сверхбыстрый супер доступ к свойствам 90978 18 февраля 00200006
Более быстрые вызовы JavaScript Внутренние внутренние. 2020 выпуск
Знак: Инструмент трассировки среды выполнения V8 tools system-analyzer
Отслеживание резерва в V8 Выпуск
V8 Release V8.5 Выпуск
V8 Release V8.4 Выпуск
Сбор мусора с высоким показателем для C ++ .
Понимание спецификации ECMAScript, часть 4 ECMAScript Понимание ECMAScript
До 4 ГБ памяти в WebAssembly выпуск
Что в этом .wasm ? ВВЕДЕНИЕ: WASM-декомпиля Инструменты WebAssembly
Понимание спецификации ECMASCRIP , часть 2 ECMAScript Понимание ECMAScript
Выпуск V8 v8. 1 Выпуск
Понимание спецификации ECMASCRICT, часть 1 ECMASCRIPT Понимание ECMASCRIPT
V8 Release V8.0
Вне веб -сайта. 2019 Инструменты WebAssembly
Выпуск версии 8 v7.9
Улучшение регулярных выражений версии 8 Внутренние компоненты RegExp
Выпуск V8 v7.8
Зажигалка V8 презентации внутренней памяти
История обрыва производительности V8 в React
High -Performarse ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015 и ES2015. 0432 17 февраля 2017 г. ECMAScript
Помогите нам протестировать будущее V8! 14 февраля 2017 г. Internals
Один маленький шаг для Chrome, одна гигантская куча для V8 09 февраля 2017 г. Память
V8 Release V5.7 06 февраль 2017 г. Выпуск
Ускорение вверх V8. internals RegExp
Как V8 измеряет реальную производительность 21 декабря 2016 эталонные тесты
V8 ❤️ Node.js 15 декабря 2016 г. Node.js
V8 Release V5.6 02 декабря 2016 г. Выпуск
Webassembly Browser Preview 31 октября 2016 Webassembly
V8 Release v5.5 24 октября 2016 Выпуск
. потребление 07 октября 2016 г. тесты памяти
Версия V8 v5. 4 09 сентября 2016 г. Версия
Запуск интерпретатора Ignition 23 августа 2016 г.0003 V8 на конференции Blinkon 6 21 июля 2016 г. Презентации
V8 Release V5.3 18 июля 2016 г. Выпуск
V8 Releas 2016 Ecmascript
V8 Release V5.1 23 апреля 2016 г. Выпуск
Jank Busters Часть вторая: Orinoco 12 апреля 2016 г. Внутренние память
V8 Release V5.0 15 марта Выпуск
Экспериментальная поддержка WebAssembly в V8 15 марта 2016 г. Webassembly
REGEXP LOUKBEHIND Утверждения 26 февраля 2016 ECMASCRIPT REGEXP
V8. Есть Math.random() , а затем Math.random() 17 декабря 2015 г. 0005 Выпуск
Jank Bussters Part One 30 октября 2015 г. Память
V8 Release V4.7 14 октября 2015 г. Выпуск
Снимок Startup Startup 25 сентября 2015 Внутренние
V8 Releas выпуск
Бесплатная сборка мусора 07 августа 2015 г. внутренняя память
Кэширование кода 27 июля 2015 г.0006
Изучение TurboFan JIT 13 июля 2015 г. Внутреннее устройство
Привет, мир! 10 July 2015
The V8 JavaScript Engine
Article Authors
Table of Contents
Other JS engines
The в поисках производительности
Компиляция
V8 — это название движка JavaScript, на котором работает Google Chrome. Это то, что берет наш JavaScript и выполняет его во время просмотра в Chrome.
V8 — это движок JavaScript, т. е. он анализирует и выполняет код JavaScript. DOM и другие API-интерфейсы веб-платформы (все они составляют среду выполнения) предоставляются браузером.
Самое интересное, что механизм JavaScript не зависит от браузера, в котором он размещен. Эта ключевая функция способствовала развитию Node.js. V8 был выбран в качестве движка, на котором работал Node.js еще в 2009 году, и когда популярность Node.js резко возросла, V8 стал движком, который теперь поддерживает невероятное количество серверного кода, написанного на JavaScript.
Экосистема Node.js огромна, и благодаря V8, который также поддерживает настольные приложения, такие как Electron.
Другие движки JS
Другие браузеры имеют свой собственный движок JavaScript:
Firefox имеет SpiderMonkey
Safari имеет JavaScriptCore (также называемый Nitro)
Edge изначально был основан на 90 перестроен с использованием Chromium и двигателя V8.
и многие другие.
Все эти механизмы реализуют стандарт ECMA ES-262, также называемый ECMAScript, стандарт, используемый JavaScript.
В поисках производительности
V8 написан на C++ и постоянно совершенствуется. Он портативный и работает на Mac, Windows, Linux и некоторых других системах.
В этом введении к V8 мы проигнорируем детали реализации V8: их можно найти на более авторитетных сайтах (например, на официальном сайте V8), и они со временем меняются, часто радикально.
V8 постоянно развивается, как и другие движки JavaScript, чтобы ускорить Интернет и экосистему Node.js.
В Интернете уже много лет идет гонка за производительностью, и мы (как пользователи и разработчики) получаем большую выгоду от этой конкуренции, поскольку из года в год мы получаем более быстрые и оптимизированные машины.
Компиляция
JavaScript обычно считается интерпретируемым языком, но современные механизмы JavaScript больше не просто интерпретируют JavaScript, они его компилируют.