Google Sheets는 Chrome에서 WasmGC를 사용하는 Google의 첫 번째 제품 중 하나입니다. 이 조치는 2022년에 발표되었으며 Sheets 및 Chrome팀은 표준화, 엔지니어링, 도구를 공동으로 사용하여 최적화에 관한 실시간 의견을 제공했습니다. 이 파트너십은 Google의 엔지니어링팀이 Chrome과 효과적으로 협력하여 더 많은 Google 앱을 WasmGC에서 실행할 수 있는 방법을 보여주는 선례가 되었습니다.
과제: JavaScript
Google Sheets 계산 엔진은 원래 Java로 작성되었으며 2006년에 출시되었습니다. 제품 초기에는 모든 계산이 서버에서 이루어졌습니다. 하지만 2013년부터 엔진은 JavaScript를 사용하여 브라우저에서 실행되었습니다. 이는 원래 Google 웹 도구 키트 (GWT)를 통해 이루어졌으며, 이후 Java to Closure JavaScript 트랜스파일러 (J2CL)를 통해 이루어졌습니다. JavaScript 계산 엔진은 웹 작업자에서 실행되며 MessageChannel
를 사용하여 기본 스레드와 통신합니다.
사용자를 서버에서 계산 엔진의 JavaScript 버전으로 이전하고 나중에 GWT에서 J2CL로 이전하는 작업은 신중한 검증이 필요한 대규모 작업이었습니다. JavaScript 계산 엔진이 Java 버전과 정확히 동일한 결과를 생성하도록 Sheets팀은 내부 유효성 검사 메커니즘을 개발했습니다. 이 메커니즘은 대규모 시트 자료 집합을 처리하고 계산 엔진의 여러 버전 간에 결과가 동일한지 확인할 수 있습니다. Sheets팀은 이 도구를 정기적으로 사용하여 Sheets의 변경사항을 검증합니다. 하지만 팀은 이러한 계산 결과를 비교하는 것뿐만 아니라 클라이언트의 JavaScript와 서버의 Java 간의 성능도 비교했습니다. 계산 엔진의 JavaScript 버전이 Java 버전보다 3배 이상 느린 것으로 나타났습니다.
JavaScript가 Java보다 느린 이유는 무엇인가요?
JavaScript는 느슨한 유형의 동적 언어에 비해 빠릅니다. 지난 15년 동안 JIT (Just-In-Time) 컴파일러 (예: Maglev, Sparkplug, Turbofan)에 대한 대규모 투자로 JavaScript의 성능이 향상되었습니다. 그러나 JavaScript의 느슨한 유형과 동적 동작으로 인해 JIT 컴파일러가 최적의 코드를 생성하기는 어렵습니다. 즉, JavaScript는 여전히 원시 처리량 측면에서 Java 및 C++와 같은 언어에 뒤처져 있습니다. TypeScript는 JavaScript에 유형 안전성을 추가하지만, 이 유형 정보는 개발을 더 쉽게 하기 위해 설계되었으며 최적의 코드를 생성하는 데 컴파일러에 필요한 보증을 제공하지는 않습니다. 대규모 스프레드시트 계산에 수십 초가 걸릴 수 있는 Google Sheets와 같은 경우 JavaScript는 빠르지만 충분히 빠르지는 않습니다.
해결 방법: WasmGC
WasmGC는 가비지 컬렉션 언어 (예: Java)를 컴파일하는 데 필요한 프리미티브를 추가하는 기존 WebAssembly 사양의 확장 프로그램입니다. 예를 들어 WasmGC는 유형을 정의하고 가비지 컬렉션된 데이터 구조를 할당하는 안내를 추가합니다. WasmGC는 가비지 컬렉션 언어 (예: Photoshop 또는 Google 어스)에 대해 Wasm이 C++에 한 것과 동일한 작업을 수행할 준비가 되었습니다. 즉, 거의 네이티브 속도로 웹에 가져오는 것입니다. Google은 가비지 컬렉션 언어의 인기로 인해 WasmGC가 Wasm보다 더 큰 영향을 미칠 수 있다고 생각합니다.
Google Workspace와 Chrome의 파트너십
WasmGC MVP 초안 사양은 2019년에 게시되었습니다. 2020년 말, Google Workspace와 Chrome은 Sheets 계산 엔진을 사용하여 WasmGC를 평가하기 위해 파트너십을 맺었습니다. Workspace의 멀티플랫폼팀은 컴파일러와 트랜스파일러를 빌드하고 최적화하는 데 상당한 전문성을 보유하고 있습니다. Workspace의 일부인 Sheets가 WasmGC를 평가하기에 이상적인 후보로 확인되었습니다. Sheets는 성능에 민감하며 강력한 성능 및 정확성 검증 메커니즘을 갖추고 있습니다. Chrome에는 WasmGC 런타임을 빌드하고 최적화하는 V8팀과 AOT (Ahead-Of-Time) 최적화를 빌드하는 Binaryen의 참여자가 있습니다. Chrome과 Workspace에는 WasmGC 도구 모음을 빌드하고 최적화하는 데 필요한 모든 전문 지식이 있으며, Google Sheets는 이상적인 테스트 환경입니다.
첫 번째 프로토타입
2021년 중반에 팀은 작동하는 Java to WasmGC 컴파일러를 보유하게 되었습니다. 같은 해 말에는 WasmGC로 실행되고 계산을 수행하는 Google Sheets의 프로토타입 버전이 있었습니다. 그 과정에서 많은 어려움을 겪었습니다. 프로파일링 및 힙 덤프를 가져오는 도구가 없으므로 빌드해야 했습니다. 기존 구현은 WasmGC용으로 대체를 찾거나 작성해야 하는 여러 JavaScript 라이브러리를 사용했습니다. 사양, 컴파일러, 새 라이브러리의 실험적 특성으로 인해 Wasm 계산 엔진의 정확성을 검증하는 데 시간이 많이 걸렸습니다. 하지만 Sheets의 유효성 검사 메커니즘이 다시 한번 큰 도움이 되었습니다. 팀은 결국 모든 문제를 해결했으며 2022년 초부터 실적 데이터가 수집되기 시작했습니다.
추가 최적화
Sheets Wasm의 초기 버전은 JavaScript보다 계산 성능이 약 2배 느렸습니다. 하지만 이는 새로운 사양, 새로운 컴파일러, 여러 새로운 라이브러리에 비해 나쁜 결과가 아닙니다. 이 시점부터 Sheets팀에서 최적화를 시작했습니다. 발견된 최적화 중 몇 가지 카테고리가 있습니다.
- Java 가상 머신 (JVM) 및 V8에 이미 존재하는 핵심 최적화를 복제합니다.
- 고도로 최적화된 브라우저 API를 사용합니다.
- JavaScript별 코딩 패턴을 삭제했습니다.
첫째, Sheets팀은 다른 도구 모음에 이미 존재하는 최적화를 복제해야 했습니다. 가상 메서드 전달 최적화가 좋은 예입니다. JVM과 V8에서는 오래 전부터 최적화되었지만 WasmGC에는 아무것도 없었습니다. 매우 일반적인 두 가지 최적화인 예상 인라인 처리 및 디버츄얼라이제이션을 구현하여 Chrome에서 계산 시간을 약 40% 단축했습니다.
두 번째로, 브라우저 API가 최적화된 네이티브 구현으로 지원되는 경우도 있는데, Wasm을 사용해 경쟁하기가 어렵습니다. 문자열과 정규 표현식이 좋은 예입니다. 특히 정규식의 경우 팀은 re2j (WasmGC로 컴파일됨)에서 Chrome의 RegExp
브라우저 API로 전환할 때 정규식 작업 속도가 거의 100배 빨라지는 것을 확인했습니다. 이 API는 각 정규식을 자체 머신 코드로 컴파일할 수 있습니다.
마지막으로 수년간의 최적화로 인해 코드베이스가 JavaScript에 과도하게 적합해진 것으로 확인되었습니다. 예를 들어 Sheets에는 배열과 맵 간의 경계가 모호해지는 핵심 데이터 구조가 있었습니다. 이는 희소 배열을 자동으로 맵으로 모델링하는 JavaScript에서는 효율적이지만 다른 플랫폼에서는 느립니다. 따라서 더 플랫폼에 구애되지 않는 방식으로 코드를 다시 작성해야 했습니다. 멀티플랫폼 애플리케이션이 웹에서 우수한 성능을 더 쉽게 얻을 수 있다는 점도 WebAssembly의 장점입니다. JavaScript의 고유한 특성에 맞게 전체 애플리케이션을 변경할 필요는 없습니다.
최종 결과
이러한 모든 최적화를 거친 Sheets의 최종 WasmGC 버전은 계산 성능이 JavaScript보다 약 2배 빠르게 실행되며, 이는 초기 WasmGC 버전의 시작점 대비 4배 향상된 것입니다.
결론
WasmGC는 개발자가 웹 애플리케이션을 빌드하는 방식을 개선할 수 있는 강력한 기술입니다. 앞으로 몇 년 동안 Google에서는 WasmGC가 공유 메모리 멀티스레딩을 지원하고 단일 스레드 성능을 더욱 개선할 수 있기를 바랍니다. 모든 웹 개발자는 다음번 고성능 프로젝트에 WasmGC를 사용하는 것을 고려해 보시기 바랍니다. Google과 함께 웹을 더 빠르고 원활하게 만들어 보세요.
감사의 말씀
WasmGC 구현 및 이 케이스 스터디에 참여해 주신 다음 분들께 감사드립니다. 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, Emanuel Ziegler