Google Sheets — один из первых продуктов Google, использующих WasmGC в Chrome. Об этом было объявлено в 2022 году, и команды Sheets и Chrome объединили усилия в области стандартизации, разработки и инструментов для предоставления обратной связи в режиме реального времени по вопросам оптимизации. Это партнерство создало прецедент того, как инженерные команды Google могут эффективно работать с Chrome, чтобы больше приложений Google могли работать на WasmGC.
Задача: JavaScript
Расчетный движок Google Sheets изначально был написан на Java и запущен в 2006 году. На ранних этапах разработки продукта все вычисления происходили на сервере. Однако с 2013 года движок работает в браузере с использованием JavaScript. Первоначально это было реализовано с помощью Google Web Toolkit ( GWT ), а позже — с помощью транспайлера JavaScript Java to Closure ( J2CL ). Расчетный движок JavaScript работает в Web Worker и взаимодействует с основным потоком через MessageChannel .
Перенос пользователей с сервера на версию вычислительного механизма на JavaScript (а позже с GWT на J2CL) был масштабной задачей, требовавшей тщательной проверки. Чтобы гарантировать, что вычислительный механизм на JavaScript выдает точно такие же результаты, как и версия на Java, команда Sheets разработала внутренний механизм проверки. Этот механизм может обрабатывать большой массив таблиц и проверять идентичность результатов в разных версиях вычислительного механизма. Команда Sheets регулярно использует этот инструмент для проверки изменений в 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. Внедрение спекулятивного встраивания и девиртуализации — двух очень распространенных оптимизаций — ускорило время вычислений примерно на 40% в Chrome.
Во-вторых, существуют случаи, когда API браузеров поддерживаются оптимизированными нативными реализациями, с которыми сложно конкурировать, используя Wasm. Строки и регулярные выражения — два хороших примера. В частности, в случае с регулярными выражениями команда наблюдала почти 100-кратное ускорение операций с регулярными выражениями при переходе от re2j (скомпилированного в WasmGC) к API браузера RegExp в Chrome, который может компилировать каждое регулярное выражение в собственный машинный код.
Наконец, они обнаружили, что годы оптимизации привели к тому, что кодовая база стала чрезмерно адаптирована под JavaScript. Например, в Sheets у них была основная структура данных, которая размывала границы между массивами и картами. Это эффективно в JavaScript, который автоматически моделирует разреженные массивы как карты, но медленно на других платформах. Поэтому им пришлось переписать код, сделав его более платформенно-независимым. Это еще один плюс WebAssembly: он упрощает создание высокопроизводительных веб-приложений для многоплатформенных приложений. Вам не нужно подстраивать все приложение под особенности JavaScript.
Окончательный результат
После всех этих оптимизаций финальная версия Sheets с поддержкой WasmGC обеспечивает производительность вычислений примерно в два раза выше, чем у JavaScript , что представляет собой четырехкратное улучшение по сравнению с исходной версией WasmGC.
Заключение
WasmGC — это мощная технология, способная кардинально изменить подход разработчиков к созданию веб-приложений. В ближайшие годы в Google мы надеемся увидеть развитие WasmGC, поддержку многопоточности с использованием общей памяти и дальнейшее повышение производительности однопоточных приложений. Мы призываем всех веб-разработчиков рассмотреть возможность использования WasmGC в своих следующих высокопроизводительных проектах. Присоединяйтесь к нам и вместе сделайте веб быстрее и эффективнее!
Благодарности
Благодарим всех, кто работал над реализацией WasmGC и этим тематическим исследованием: Диваса Адхикари, Мэтью Олбрайта, Ксению Букину, Жюльена Драме, Асима Фазала, Майкла Фредерика, Гоктуга Гокдогана, Джанис Гу, Адама Кляйна, Маноса Кукутоса, Якоба Куммерова, Маттиаса Лидтке, Томаса Лайвли, Роберто Люблинермана, Вишрута Мехту, Томаса Наттестада, Джоша Перлштейна, Хоакима Перотти, Криса Руэнеса, Стивена Савиано, Дерека Шуффа, Тима Сирса, Майкла Томаса, Юань Тяня, Филиппа Вайса, Мейсона Ву, Алона Закая и Эмануэля Зиглера.