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

Да, есть несколько практик, которые могут ускорить работу вашего кода, все они основаны на том, как внутри работает движок Google JS, V8. Движок V8 сам по себе довольно крутая технология, и если когда-нибудь вам захочется приключений, вы можете посмотреть его исходный код (да, это мое представление об авантюрах, не судите строго).

Немного о V8

V8, пожалуй, самый быстрый JS-движок, и он делает несколько трюков, чтобы получить этот титул. Одним из них является компиляция Just In Time или JIT (ее используют все современные движки). Итак… в отличие от компилируемых языков, таких как C++, JS компилируется во время выполнения программы.

Компилятору нужно как можно больше информации для вывода быстрого, эпического, изменяющего мир машинного кода, но мы, разработчики JS, не очень любим предоставлять информацию с помощью динамической системы типов JS.
Чтобы дополнить непредсказуемость разработчиков JS, V8 имеет адаптироваться, и решение использует два компилятора (ура!).

Во-первых, базовый компилятор преобразует весь JS-код в машинный код, как обычные компиляторы, которые вы видите на любом другом языке, и, честно говоря, это очень скучно. Базовый компилятор быстрее компилирует JS в машинный код по сравнению с другим компилятором, который мы обсудим. Вывод машинного кода базового компилятора неоптимизирован и поэтому выполняется медленнее.

Другой, оптимизирующий компилятор, как следует из названия, оптимизирует код. Именно этот компилятор мы хотим использовать для сверхбыстрого JS. Оптимизирующий компилятор отслеживает так называемые горячие функции. По сути, функция, которую часто называют горячей 🔥. Оптимизирующий компилятор генерирует оптимизированный машинный код для этих функций.

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

Оптимизированный машинный код и деоптимизация

Оптимизированный машинный код (OMC) для функции специфичен для одной сигнатуры функции и формы параметра. Этот OMC сохраняется, и позже, когда та же функция вызывается с той же формой параметра вместо кода из базового компилятора, используется сохраненная OMC.
Что такое форма? В основном это свойства, определенные для объекта, и в каком порядке.
Итак…. OMC генерируется для каждой горячей функции для каждой формы, для которой вы ее вызываете, и сохраняется, что ж, спасибо, V8!. Но дело в том, что V8 также имеет свои ограничения, он не может просто генерировать OMC для сотен способов вызова функции, в стандартных условиях V8 генерирует OMC для 4 форм 1 функции, это означает, что если вы вызываете функцию в своем коде с более чем 5 форм параметров V8 не будет считать его горячим, независимо от того, как часто его вызывают, это называется деоптимизацией. Чтобы получить максимальную производительность от вашего JS-приложения, мы должны писать код, который максимально использует оптимизированный компилятор и избегает деоптимизации, так как же нам это сделать?

Оставайся в форме

Да, трюк прост. Видите ли, если мы каждый раз будем вызывать нашу функцию с одной и той же сигнатурой и формой объекта, V8 сможет использовать OMC для запуска этой функции.
Вот пример плохо оптимизированного кода.

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

как видите, добавив неопределенные свойства объекта, мы сохранили форму параметров, поэтому деоптимизации не будет.

Другие быстрые советы

  1. Избегайте переназначения переменной значений другого типа.
  2. По возможности используйте константные переменные.
  3. Попробуйте определить свойства объекта так, как вы его объявляете.