Перейти к основному содержимому

Изучение TurboFan JIT

· 3 мин. чтения
Бен Л. Титцер, инженер-программист и механик TurboFan

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

Производительность всегда была ядром стратегии V8. TurboFan сочетает передовое промежуточное представление с многоуровневым конвейером перевода и оптимизации, чтобы генерировать машинный код более высокого качества, чем это было возможно ранее с CrankShaft JIT. Оптимизации в TurboFan многочисленнее, сложнее и применяются более основательно, чем в CrankShaft, позволяя гибкoе перемещение кода, оптимизацию управления потоком и точный анализ числовых диапазонов, что ранее было недостижимо.

Слоистая архитектура​

С течением времени компиляторы обычно усложняются, поскольку поддерживаются новые функции языка, добавляются новые оптимизации и нацеливается поддержка новых архитектур компьютеров. С TurboFan мы извлекли уроки из многих компиляторов и разработали слоистую архитектуру, позволяющую компилятору справляться с этими требованиями со временем. Более четкое разделение между языком исходного уровня (JavaScript), возможностями VM (V8) и особенностями архитектуры (от x86 до ARM до MIPS) позволяет создавать более чистый и надежный код. Слоистая структура позволяет разработчикам компилятора локально анализировать при внедрении оптимизаций и функций, а также писать более эффективные модульные тесты. Это также экономит код. Каждая из 7 целевых архитектур, поддерживаемых TurboFan, требует меньше 3000 строк кода, специфичного для платформы, в сравнении с 13000-16000 в CrankShaft. Это позволило инженерам ARM, Intel, MIPS и IBM более эффективно вносить вклад в TurboFan. TurboFan гораздо легче поддерживает все предстоящие функции ES6 благодаря своему гибкому дизайну, отделяющему фронтенд JavaScript от зависимых от архитектуры бекендов.

Более сложные оптимизации​

TurboFan JIT реализует более агрессивные оптимизации, чем CrankShaft, используя ряд продвинутых методов. JavaScript поступает в конвейер компилятора в основном не оптимизированной форме и переводится и оптимизируется до все более низких форм, пока не будет сгенерирован машинный код. Центральным элементом конструкции является более гибкое внутреннее представление в виде "моря узлов" (IR) кода, которое позволяет более эффективно перестраивать и оптимизировать.

Пример графа TurboFan

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

Достижение нового уровня производительности​

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