Disclaimer | ДисклеймерУметь писать код - хорошо.
Уметь писать код хорошо - отлично.
Но чтобы писать код хорошо, по-мимо прочего, очень важным фактором является факт понимания, как работают инструменты и технологии, с которыми мы взаимодействуем.
V8
Часть 1.
Рано или поздно каждый сталкивался с высказываниями, что язык JavaScript - язык медленный.
Однако, в том же Chrome или, например, Node.js, все происходит достаточно быстро. Почему?
Почти всё, благодаря JIT-компилятору, который встроен в движок V8.
Магия?
Чтобы лучше понять что происходит, стоит немного рассмотреть, глобально, архитектуру, систему, того, что происходит с кодом. Как дело доходит, непосредственно, до его выполнения.
Существуют 2 основных пути - компилирование кода, и интерпретирование кода.
Если не вдаваться в подробности (тема, действительно, невообразимо обширна), можно представить, что JavaScript - это ноты.
Интерпретатор - пианист, который видит эти ноты впервые. Он читает их, и играет мелодию прямо по нотам, не зная того, что будет дальше (это не совсем так, но принцип именно такой)
Способен начать играть мелодию сразу, но каждый раз, играя ее, он будет заново обрабатывать каждую ноту.
Компилятор - это пианист, который сначала учит ноты, наизусть. Простраивает в голове модели того, как должна звучать мелодия, где должын быть акценты, а уже после - играет мелодию по памяти.
Необходима долгая подготовка, но после - моментальное исполнение.
Движок V8, использует два уровня (и еще огромную массу оптимизаций, которые подробно затрагивать, мы сейчас не будем)
На первом этапе, работает Ignition - сверхлегкий интерпретатор.
Быстрый старт: V8 сначала прогоняет код через Ignition.
После, генерирует байткод (это что-то среднее между JavaScript и машинным кодом). И в конце, cобирает данные о том, какие функции вызываются чаще всего.
Зачем? Чтобы не тратить время на компиляцию всего кода сразу.
На втором этапе, работает TurboFan — оптимизирующий компилятор.
Когда функция вызывается много раз, V8 передаёт её в TurboFan. Тут и начинается, та самая магия:
Во-первых, проводится анализ типов: V8 смотрит, какие типы данных ты используешь (числа, строки, объекты).
Во-вторых, проводится специализация кода - если функция 100 раз вызвана с числами — TurboFan генерирует машинный код только для чисел.
По-мимо описанных выше процессов, производится инлайн-подстановка: маленькие функции (вроде x + y) вставляются прямо в вызывающий код, без лишних вызовов.
И наконец, производится удаление мёртвого кода: Если условие if (false) { ... } — TurboFan вырежет его.
В результате - код выполняется ПОЧТИ как нативый С++
Это почти все. Существует 3-ий этап - деоптимизация
Происходит это в том случае, если, например: функция стабильно работала с числами, а в какой-то момент получила - строку.
V8 откатывает оптимизацию и возвращается к Ignition. Процесс - медленный. Именно поэтому, стабильные типы = быстрый код.
В следующих частях углубимся в тему, и разберем профилирования и скрытые классы
// Поставь реакцию!
t.me/aif_sn