Arkusze Google to jedna z pierwszych usług Google, która korzysta z WasmGC w Chrome. Ta zmiana została ogłoszona w 2022 roku. Zespoły Arkuszy i Chrome współpracowały ze sobą w zakresie standaryzacji, inżynierii i narzędzi, aby zapewnić informacje zwrotne na temat optymalizacji w czasie rzeczywistym. To partnerstwo wyznaczyło nowy kierunek współpracy zespołów inżynierów Google z Chrome, aby umożliwić uruchamianie większej liczby aplikacji Google w usłudze WasmGC.
Wyzwanie: JavaScript
Silnik obliczeniowy Arkuszy Google został pierwotnie napisany w Javie i wprowadzony w 2006 r. Na początku rozwoju usługi wszystkie obliczenia były wykonywane na serwerze. Od 2013 r. silnik działa jednak w przeglądarce za pomocą JavaScriptu. Początkowo było to realizowane za pomocą Google Web Toolkit (GWT), a później za pomocą transpilatora Java to Closure JavaScript (J2CL). Silnik obliczeniowy JavaScript działa w workerze internetowym i komunikuje się z głównym wątkiem za pomocą MessageChannel
.
Migracja użytkowników z serwera na wersję JavaScriptową mechanizmu obliczeniowego (a później z GWT na J2CL) była dużym przedsięwzięciem, które wymagało dokładnej weryfikacji. Aby mieć pewność, że mechanizm obliczeniowy JavaScriptu daje dokładnie takie same wyniki jak wersja w Javie, zespół Arkuszy Google opracował wewnętrzny mechanizm weryfikacji. Ten mechanizm może przetwarzać duży zbiór arkuszy i sprawdzać, czy wyniki są identyczne w przypadku wielu wersji mechanizmu obliczeniowego. Zespół Arkuszy Google regularnie używa tego narzędzia do sprawdzania zmian w Arkuszach Google. Zespół nie tylko porównał wyniki tych obliczeń, ale też porównał wydajność JavaScript na kliencie i Javy na serwerze. Okazało się, że wersja silnika obliczeniowego w JavaScript była ponad 3 razy wolniejsza niż wersja w Java.
Dlaczego JavaScript jest wolniejszy niż Java?
JavaScript jest szybki jak na język dynamiczny o luźnym typowaniu. W ciągu ostatnich 15 lat znaczne inwestycje w kompilatory just-in-time (JIT) (np. Maglev, Sparkplug i Turbofan) zwiększyły wydajność JavaScriptu. Jednak ze względu na luźne typy i dynamiczne zachowanie JavaScriptu kompilatory JIT mają trudności z generowaniem optymalnego kodu. Oznacza to, że JavaScript nadal pozostaje w tyle za językami takimi jak Java czy C++, jeśli chodzi o przepustowość. TypeScript zwiększa bezpieczeństwo typów w JavaScript, ale te informacje o typach mają ułatwić rozwój, a nie zapewnić tego rodzaju gwarancji, których potrzebują kompilatory do generowania optymalnego kodu. W przypadku Arkuszy Google, gdzie obliczenia dużych arkuszy mogą zająć kilkadziesiąt sekund, JavaScript jest szybki, ale nie wystarczająco szybki.
Rozwiązanie: WasmGC
WasmGC to rozszerzenie istniejącej specyfikacji WebAssembly, które dodaje elementy potrzebne do kompilowania języków z zbieraniem elementów odśmieci (takich jak Java). Na przykład WasmGC dodaje instrukcje definiowania typów i przydzielania struktur danych z zbieraniem elementów do usunięcia. WasmGC ma za zadanie zrobić z językami z zbieraniem z wykorzystaniem zbiornika na dane to, co Wasm zrobił z C++ (np. Photoshop czy Google Earth), czyli udostępnić je w internecie z prawie natywną szybkością. W Google uważamy, że WasmGC może mieć jeszcze większy wpływ niż Wasm, ponieważ języki z zbieraniem śmieci są popularne.
Google Workspace współpracuje z Chrome
W 2019 r. opublikowano projekt specyfikacji MVP WasmGC. Pod koniec 2020 r. Google Workspace i Chrome nawiązały współpracę, aby ocenić WasmGC za pomocą mechanizmu obliczeniowego Arkuszy. Zespół Workspace zajmujący się platformami ma duże doświadczenie w tworzeniu i optymalizowaniu kompilatorów oraz transpilacji. Arkusze Google, które są częścią Workspace, zostały uznane za idealny kandydata do oceny WasmGC: aplikacja ta jest wrażliwa na wydajność i ma solidne mechanizmy weryfikacji wydajności i poprawności. W Chrome jest zespół V8, który tworzy i optymalizuje środowisko wykonawcze WasmGC, a także współpracownicy Binaryen, którzy tworzą optymalizacje AOT (z wyprzedzeniem). Chrome i Workspace zapewniają wszystkie niezbędne informacje do tworzenia i optymalizowania łańcucha narzędzi WasmGC, a Arkusze Google są idealnym miejscem do testowania.
Pierwszy prototyp
W połowie 2021 r. zespoły miały działający kompilator Java na WasmGC. Pod koniec tego samego roku prototyp Arkuszy Google działał jako WasmGC i wykonywał obliczenia. Po drodze napotkali wiele wyzwań. Narzędzia do profilowania i tworzenia dumpów stosu nie istniały i trzeba je było stworzyć. Dotychczasowa implementacja wykorzystywała wiele bibliotek JavaScript, które trzeba było znaleźć lub napisać na potrzeby WasmGC. Weryfikacja poprawności silnika obliczeniowego Wasm wymagała sporo czasu ze względu na eksperymentalny charakter specyfikacji, kompilatora i nowych bibliotek. Jednak mechanizmy sprawdzania arkuszy były znowu bardzo pomocne. Ostatecznie wszystko zaczęło działać, a na początku 2022 r. zaczęły napływać dane o skuteczności.
Dodatkowe optymalizacje
Początkowa wersja Wasm w Arkuszach wykazała, że obliczenia są wykonywane około 2 razy wolniej niż w JavaScript. Nie jest to jednak zły wynik, biorąc pod uwagę nową specyfikację, nowy kompilator i kilka nowych bibliotek. Od tego momentu zespół Arkuszy zaczął optymalizować. Wśród znalezionych optymalizacji wyróżniliśmy kilka kategorii:
- powielanie optymalizacji jądra, które istniały już w maszynie wirtualnej Java (JVM) i w V8;
- Korzystanie z optymalizowanych interfejsów API przeglądarki.
- Usuwanie wzorów kodowania specyficznych dla JavaScriptu.
Po pierwsze zespół arkuszy kalkulacyjnych musiał odtworzyć optymalizacje, które istnieją już w innych łańcuchach narzędzi. Najlepszym przykładem jest optymalizacja wysyłania wywołań metod wirtualnych, które od dawna są optymalizowane przez JVM i V8, ale nie było nic dla WasmGC. Wdrożenie speculatywnego wstawiania kodu i dewirtualizacji – dwóch bardzo popularnych optymalizacji – skróciło czas obliczeń w Chrome o około 40%.
Po drugie, są przypadki, w których interfejsy API przeglądarki są obsługiwane przez zoptymalizowane natywne implementacje, które trudno jest zastąpić za pomocą Wasm. Przykładami takich danych są ciągi znaków i wyrażenia regularne. W szczególności w przypadku wyrażeń regularnych zespół zauważył prawie 100-krotne przyspieszenie operacji wyrażeń regularnych po przejściu z re2j (skompilowanego do WasmGC) na interfejs API przeglądarki RegExp
w Chrome, który może kompilować każde wyrażenie regularne do własnego kodu maszynowego.
W końcu okazało się, że lata optymalizacji spowodowały, że kod źródłowy jest zbytnio dostosowany do JavaScriptu. Na przykład mieli podstawową strukturę danych w Arkuszach, która zacierała różnice między tablicami a mapami. Jest to skuteczne w przypadku JavaScriptu, który automatycznie modeluje rzadkie tablice jako mapy, ale działa wolno na innych platformach. Musieli więc przepisać kod w sposób bardziej niezależny od platformy. To kolejna zaleta WebAssembly: ułatwia ono aplikacjom wieloplatformowym osiąganie dobrej wydajności w internecie. Nie musisz dostosowywać całej aplikacji do specyfiki JavaScript.
Ostateczny wynik
Po zastosowaniu wszystkich tych optymalizacji ostateczna wersja WasmGC w Arkuszach osiąga wydajność obliczeń dwa razy większą niż JavaScript, co oznacza czterokrotny wzrost w stosunku do początkowej wersji WasmGC.
Podsumowanie
WasmGC to zaawansowana technologia, która może usprawnić tworzenie aplikacji internetowych przez programistów. W nadchodzących latach mamy nadzieję, że WasmGC będzie się rozwijać, aby obsługiwać wielowątkowość z wspólnej pamięci i dalej poprawiać wydajność pojedynczego wątku. Zachęcamy wszystkich web developerów do rozważenia zastosowania WasmGC w przyszłych projektach o wysokiej wydajności. Dołącz do nas i pomóż nam sprawić, aby internet był szybszy i płynniejszy.
Podziękowania
Dziękujemy osobom, które pracowały nad wdrożeniem WasmGC i tym przypadkiem użycia: Diwas Adhikary, Matthew Albright, Ksenia Bukina, Julien Dramaix, Asim Fazal, Michael Frederick, Goktug Gokdogan, Janice Gu, Adam Klein, Manos Koukoutos, Jakob Kummerow, Matthias Liedtke, Thomas Lively, Roberto Lublinerman, Vishrut Mehta, Thomas Nattestad, Josh Pearlstein, Joaquim Perotti, Chris Ruenes, Steven Saviano, Derek Schuff, Tim Sears, Michael Thomas, Yuan Tian, Philipp Weis, Mason Wu, Alon Zakai i Emanuel Ziegler.