Arkusze Google to jedna z pierwszych usług Google, która korzysta z WasmGC w Chrome. Zmiana została ogłoszona w 2022 roku. Zespoły Arkuszy i Chrome współpracowały nad standaryzacją, inżynierią i narzędziami, aby dostarczać opinie o optymalizacjach w czasie rzeczywistym. Ta współpraca wyznaczyła precedens dla tego, jak zespoły inżynierskie w Google mogą skutecznie współpracować z zespołem Chrome, aby więcej aplikacji Google działało w WasmGC.
Wyzwanie: JavaScript
Silnik obliczeniowy Arkuszy Google został pierwotnie napisany w Javie i uruchomiony w 2006 roku. Na początku wszystkie obliczenia były wykonywane na serwerze. Od 2013 r. wyszukiwarka działa jednak w przeglądarce przy użyciu JavaScriptu. Początkowo było to możliwe dzięki Google Web Toolkit (GWT), a później dzięki transpilatorowi Java do Closure JavaScript (J2CL). Silnik obliczeniowy JavaScript działa w instancji roboczej i komunikuje się z głównym wątkiem za pomocą MessageChannel.
Przeniesienie użytkowników z serwera do wersji silnika obliczeniowego w JavaScript (a później z GWT do J2CL) było dużym przedsięwzięciem, które wymagało starannej weryfikacji. Aby mieć pewność, że silnik obliczeniowy JavaScriptu daje dokładnie takie same wyniki jak wersja w języku Java, zespół Arkuszy opracował wewnętrzny mechanizm weryfikacji. Ten mechanizm może przetwarzać duży zbiór arkuszy i sprawdzać, czy wyniki są identyczne w różnych wersjach silnika obliczeniowego. Zespół Arkuszy regularnie używa tego narzędzia do weryfikowania zmian w Arkuszach. Zespół nie tylko porównał wyniki tych obliczeń, ale także skuteczność JavaScriptu po stronie klienta i Javy po stronie serwera. Okazało się, że wersja silnika obliczeniowego w JavaScript była ponad 3 razy wolniejsza niż wersja w Javie.
Dlaczego JavaScript jest wolniejszy od Javy?
JavaScript jest szybki jak na język dynamiczny o słabym typowaniu. Intensywne inwestycje w kompilatory JIT (np. Maglev, Sparkplug i Turbofan) w ciągu ostatnich 15 lat zwiększyły wydajność JavaScriptu. Jednak luźne typy i dynamiczne zachowanie JavaScriptu utrudniają kompilatorom JIT generowanie optymalnego kodu. Oznacza to, że JavaScript nadal ustępuje językom takim jak Java i C++ pod względem przepustowości. TypeScript zwiększa bezpieczeństwo typów w JavaScript, ale informacje o typach mają ułatwiać programowanie, a nie zapewniać gwarancji potrzebnych kompilatorom do generowania optymalnego kodu. W przypadku takich usług jak Arkusze Google, w których obliczanie dużych arkuszy kalkulacyjnych może trwać dziesiątki sekund, JavaScript jest szybki, ale nie wystarczająco.
Rozwiązanie: WasmGC
WasmGC to rozszerzenie istniejącej specyfikacji WebAssembly, które dodaje elementy pierwotne potrzebne do kompilowania języków z odśmiecaniem pamięci (takich jak Java). Na przykład WasmGC dodaje instrukcje definiowania typów i przydzielania struktur danych podlegających odśmiecaniu. WasmGC ma szansę zrobić dla języków z odśmiecaniem pamięci to, co Wasm zrobił dla C++ (np. Photoshop czy Google Earth), czyli przenieść je do internetu z prędkością zbliżoną do natywnej. W Google uważamy, że WasmGC może mieć jeszcze większy wpływ niż Wasm ze względu na popularność języków z odśmiecaniem pamięci.
Współpraca Google Workspace z Chrome
Projekt specyfikacji MVP WasmGC został opublikowany w 2019 roku. Pod koniec 2020 roku zespoły Google Workspace i Chrome przeprowadziły wspólnie testy WasmGC przy użyciu silnika obliczeniowego Arkuszy. Zespół Workspace ds. wielu platform ma duże doświadczenie w tworzeniu i optymalizowaniu kompilatorów i transpilatorów. Arkusz kalkulacyjny, który jest częścią Workspace, został uznany za idealny do oceny WasmGC: jest wrażliwy na wydajność i ma solidne mechanizmy weryfikacji wydajności i poprawności. Zespół V8 w Chrome tworzy i optymalizuje środowisko wykonawcze WasmGC, a współtwórcy projektu Binaryen opracowują optymalizacje kompilacji z wyprzedzeniem (AOT). Dzięki połączeniu Chrome i Workspace mamy całą wiedzę potrzebną do tworzenia i optymalizowania łańcucha narzędzi WasmGC, a Arkusze Google są idealnym środowiskiem testowym.
Pierwszy prototyp
Do połowy 2021 r. zespoły opracowały działający kompilator z Javy do WasmGC. Pod koniec tego samego roku mieli już prototyp Arkuszy Google działający jako WasmGC i wykonujący obliczenia. Po drodze napotkali wiele wyzwań. Narzędzia do profilowania i tworzenia zrzutów sterty nie istniały i musieliśmy je zbudować. Dotychczasowa implementacja korzystała z wielu bibliotek JavaScript, które trzeba było zastąpić lub napisać od nowa na potrzeby WasmGC. Sprawdzanie poprawności silnika obliczeniowego Wasm było czasochłonne ze względu na eksperymentalny charakter specyfikacji, kompilatora i nowych bibliotek. Ale mechanizmy weryfikacji w Arkuszach Google okazały się po raz kolejny niezwykle pomocne. Zespołom udało się w końcu wszystko uruchomić, a dane o skuteczności zaczęły napływać na początku 2022 roku.
Dodatkowe optymalizacje
Początkowa wersja Arkuszy Google Wasm wykazywała wydajność obliczeniową około 2 razy wolniejszą niż 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ć działanie usługi. Wśród znalezionych optymalizacji pojawiło się kilka kategorii:
- Powielanie podstawowych optymalizacji, które już istniały w maszynie wirtualnej Java (JVM) i V8.
- Korzystanie z wysoce zoptymalizowanych interfejsów API przeglądarki.
- usuwanie wzorców kodowania specyficznych dla JavaScriptu;
Po pierwsze, zespół Arkuszy musiał odtworzyć optymalizacje, które już istnieją w innych łańcuchach narzędzi. Najlepszym przykładem jest optymalizacja wirtualnego wysyłania metod, która od dawna jest optymalizowana przez JVM i V8, ale nie istniała w przypadku WasmGC. Wdrożenie spekulatywnego wstawiania i dewirtualizacji – 2 bardzo popularnych optymalizacji – przyspieszyło czas obliczeń w Chrome o około 40%.
Po drugie, istnieją przypadki, w których interfejsy API przeglądarki są oparte na zoptymalizowanych implementacjach natywnych, z którymi trudno konkurować za pomocą Wasm. Dobrymi przykładami są ciągi znaków i wyrażenia regularne. W przypadku wyrażeń regularnych zespół odnotował prawie 100-krotne przyspieszenie operacji na wyrażeniach regularnych po przejściu z re2j (skompilowanego do WasmGC) na interfejs API przeglądarki RegExp w Chrome, który może skompilować każde wyrażenie regularne do własnego kodu maszynowego.
Odkryli też, że lata optymalizacji spowodowały nadmierne dopasowanie bazy kodu do JavaScriptu. Na przykład mieli podstawową strukturę danych w Arkuszach, która zacierała granice między tablicami a mapami. Jest to wydajne w JavaScript, który automatycznie modeluje tablice rzadkie jako mapy, ale powolne na innych platformach. Dlatego musieli napisać kod w sposób bardziej niezależny od platformy. To kolejna zaleta WebAssembly, którą docenia zespół: ułatwia ona aplikacjom wieloplatformowym osiąganie dobrej wydajności w internecie. Nie musisz dostosowywać całej aplikacji do specyfiki JavaScriptu.
Wynik końcowy
Po wszystkich tych optymalizacjach końcowa wersja Arkuszy w WasmGC osiąga wydajność obliczeniową około 2 razy większą niż JavaScript, co oznacza 4-krotny wzrost w porównaniu z początkową wersją WasmGC.
Podsumowanie
WasmGC to zaawansowana technologia, która może zmienić sposób tworzenia aplikacji internetowych przez programistów. W Google mamy nadzieję, że w najbliższych latach WasmGC będzie obsługiwać wielowątkowość z pamięcią współdzieloną i jeszcze bardziej poprawi wydajność jednowątkową. Zachęcamy wszystkich deweloperów stron internetowych do używania WasmGC w kolejnych projektach wymagających wysokiej wydajności. Dołącz do nas i spraw, aby internet działał szybciej i płynniej.
Podziękowania
Dziękujemy osobom, które pracowały nad implementacją WasmGC i tym studium przypadku: 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.