Почему Google Таблицы перенесли свой вычислительный инструмент с JavaScript на WasmGC

Google Таблицы — один из первых продуктов Google, использующих WasmGC в Chrome. Об этом шаге было объявлено в 2022 году, и команды Sheets и Chrome начали сотрудничать в области стандартизации, проектирования и инструментов, чтобы предоставлять обратную связь по оптимизации в режиме реального времени. Это партнерство создало прецедент того, как инженерные группы Google могут эффективно работать с Chrome, чтобы больше приложений Google работало на WasmGC.

Задача: JavaScript

Механизм вычислений Google Sheets изначально был написан на Java и запущен в 2006 году. На заре существования продукта все вычисления выполнялись на сервере. Однако с 2013 года движок работает в браузере с использованием JavaScript. Первоначально это было достигнуто с помощью Google Web Toolkit ( GWT ), а затем с помощью транспилятора Java to Closure JavaScript ( J2CL ). Механизм вычислений JavaScript работает в Web Worker и взаимодействует с основным потоком с помощью MessageChannel .

Миграция пользователей с сервера на версию вычислительной машины JavaScript (а позже с GWT на J2CL) была серьезной задачей, требовавшей тщательной проверки. Чтобы гарантировать, что механизм вычислений JavaScript дает точно такие же результаты, что и версия Java, команда Sheets разработала внутренний механизм проверки. Этот механизм может обрабатывать большой массив листов и проверять идентичность результатов в нескольких версиях механизма вычислений. Команда Таблиц регулярно использует этот инструмент для проверки изменений в Таблицах. Но команда не просто сравнила результаты этих вычислений, они также сравнили производительность JavaScript на клиенте и Java на сервере. Они обнаружили, что версия вычислительной машины на JavaScript более чем в три раза медленнее, чем версия на Java.

Почему JavaScript медленнее Java?

JavaScript работает быстро для свободно типизированного динамического языка. Крупные инвестиции в JIT-компиляторы (например, Maglev , Sparkplug и Turbofan ) за последние 15 лет увеличили производительность JavaScript. Однако свободные типы и динамическое поведение JavaScript затрудняют создание оптимального кода JIT-компиляторами. Это означает, что JavaScript по-прежнему отстает от таких языков, как Java и C++, по производительности. TypeScript добавляет безопасность типов в JavaScript, но эта информация о типах предназначена для облегчения разработки, а не для предоставления каких-то гарантий, необходимых компиляторам для генерации оптимального кода. В таких случаях, как Google Sheets, где расчет больших таблиц может занять десятки секунд, JavaScript работает быстро, но недостаточно быстро.

Решение: WasmGC

WasmGC — это расширение существующей спецификации WebAssembly , которое добавляет примитивы, необходимые для компиляции языков со сборкой мусора (таких как Java). Например, WasmGC добавляет инструкции для определения типов и выделения структур данных, собираемых мусором. WasmGC готов сделать для языков со сборкой мусора то же, что Wasm сделал для C++ (например, Photoshop или Google Earth ), то есть перенести их в Интернет со скоростью, близкой к естественной. В Google мы считаем, что WasmGC может оказаться даже более эффективным, чем Wasm, из-за популярности языков со сборщиком мусора.

Google Workspace сотрудничает с Chrome

Черновой вариант спецификации WasmGC MVP был опубликован в 2019 году. В конце 2020 года Google Workspace и Chrome объединились для оценки WasmGC с использованием вычислительной системы Sheets. Мультиплатформенная команда Workspace обладает значительным опытом создания и оптимизации компиляторов и транспиляторов. Sheets, часть Workspace, была признана идеальным кандидатом для оценки WasmGC: она чувствительна к производительности и имеет надежные механизмы проверки производительности и правильности. У Chrome есть команда V8 для создания и оптимизации среды выполнения WasmGC, а также участники Binaryen для создания предварительной оптимизации (AOT). Chrome и Workspace обладают всем необходимым опытом для создания и оптимизации цепочки инструментов WasmGC, а Google Sheets — идеальным испытательным стендом.

Первый прототип

К середине 2021 года у команд был работающий компилятор Java для WasmGC . К концу того же года у них появился прототип версии Google Sheets, работающий под именем WasmGC и выполняющий вычисления. По пути они столкнулись со многими проблемами. Инструментов для профилирования и получения дампов кучи не существовало, и их нужно было создать. Существующая реализация опиралась на множество библиотек JavaScript, которым нужно было найти замену или написать для WasmGC. Проверка правильности вычислительного механизма Wasm заняла много времени из-за экспериментального характера спецификации, компилятора и новых библиотек. Но механизмы проверки Sheets снова оказались чрезвычайно полезными. В конечном итоге команды заработали, и данные о производительности начали поступать в начале 2022 года.

Дополнительные оптимизации

Первоначальная версия Sheets Wasm показала производительность вычислений примерно в два раза медленнее, чем JavaScript. Однако это неплохой результат для новой спецификации, нового компилятора и нескольких новых библиотек. С этого момента команда Sheets начала оптимизацию. Из найденных ими оптимизаций выделилось несколько категорий:

  • Репликация основных оптимизаций, которые уже существовали в виртуальной машине Java (JVM) и в V8.
  • Использование высокооптимизированных API браузера.
  • Удаление шаблонов кодирования, специфичных для JavaScript.

Во-первых, команде Sheets необходимо было воспроизвести оптимизации, которые уже существуют в других цепочках инструментов. Лучшим примером этого является оптимизация диспетчеризации виртуальных методов , которая уже давно оптимизирована для JVM и V8, но для WasmGC ничего не существовало. Реализация спекулятивной встраивания и девиртуализации — двух очень распространенных оптимизаций — ускорила время вычислений в Chrome примерно на 40%.

Во-вторых, бывают случаи, когда API браузера поддерживаются оптимизированными собственными реализациями, с которыми трудно конкурировать при использовании Wasm. Строки и регулярные выражения — два хороших примера. В частности, что касается регулярных выражений, команда заметила почти 100-кратное ускорение операций с регулярными выражениями при переходе от re2j (скомпилированного в WasmGC) к API браузера RegExp в Chrome, который может компилировать каждое регулярное выражение в свой собственный машинный код.

Наконец, они обнаружили, что годы оптимизации привели к тому, что кодовая база была перенастроена на JavaScript. Например, у них была базовая структура данных в Таблицах, которая стирала границы между массивами и картами. Это эффективно в JavaScript, который автоматически моделирует разреженные массивы как карты, но медленно на других платформах. Поэтому им пришлось переписать код, сделав его более независимым от платформы. Это еще одна вещь, которая нравится команде в WebAssembly: с ее помощью многоплатформенным приложениям легче добиться хорошей производительности в Интернете. Вам не обязательно подстраивать все свое приложение под особенности JavaScript.

Окончательный результат

После всех этих оптимизаций окончательная версия Sheets для WasmGC обеспечивает производительность вычислений примерно в два раза выше, чем в JavaScript , что представляет собой четырехкратное улучшение по сравнению с исходной версией WasmGC.

Заключение

WasmGC — это мощная технология, которая может улучшить способы создания веб-приложений разработчиками. В ближайшие годы мы в Google надеемся увидеть, как WasmGC будет поддерживать многопоточность с общей памятью и еще больше улучшит однопоточную производительность. Мы призываем всех веб-разработчиков рассмотреть возможность использования WasmGC для своего следующего высокопроизводительного проекта. Присоединяйтесь к нам и вместе сделайте Интернет быстрее и удобнее!

Благодарности

Спасибо тем, кто работал над реализацией WasmGC и этим практическим примером: Дивас Адикари, Мэтью Олбрайт, Ксения Букина, Жюльен Драма, Асим Фазал, Майкл Фредерик, Гоктуг Гокдоган, Дженис Гу, Адам Кляйн, Манос Кукутос, Якоб Куммеров, Матиас Лидтке, Томас Лайвли, Роберто Люблинерман, Вишрут Мехта, Томас Наттестад, Джош Перлштейн, Хоаким Перотти, Крис Руенес, Стивен Савиано, Дерек Шуфф, Тим Сирс, Майкл Томас, Юань Тиан, Филипп Вайс, Мейсон Ву, Алон Закай и Эмануэль Зиглер.