Notionブラウザ版、WebAssembly版SQLite3でページ遷移速度を20%改善 実装時の苦労と教訓とは?:クロスオリジン分離も課題
Notion Labsは公式ブログで、NotionのデータキャッシュにWebAssembly実装の「SQLite3 WASM/JS」を採用した事例を紹介する記事を公開した。適用に至るまでの苦労や教訓を明らかにしている。
クロスプラットフォームのワークスペースアプリ「Notion」を提供するNotion Labsは2024年7月10日(米国時間)に公式ブログで、NotionのブラウザバージョンのデータキャッシュにWebAssembly(WASM)実装の「SQLite3 WASM/JS」(以後、WASM版SQLite3)を採用した事例を紹介する記事を公開した。
2021年ごろ、WindowsおよびmacOS版のNotionデスクトップアプリにおけるパフォーマンス向上を目的にSQLiteを採用した同社は、ネイティブのモバイルアプリでもSQLiteを採用してきた。そして、ブラウザ版アプリには、WASM版SQLite3を採用したという。
Notion Labsは「WASM版SQLite3を採用することで、全ての最新ブラウザでページ間の遷移のパフォーマンスを20%改善できた。インターネット接続など外部要因によりAPIのレスポンス時間が遅いユーザーにとっては顕著だった。オーストラリアのユーザーは28%、中国のユーザーは31%、インドのユーザーは33%高速化している」と述べている。
Notion Labsは、WASM版SQLite3の適用に至るまでの苦労や採用の成果、教訓を次のように説明している。
WASM版SQLite3導入における実装の課題 どのようなアーキテクチャを検討したのか
セッション間でデータを永続化するために、WASM版SQLite3は「OPFS」(Origin Private File System)を使用している。OPFSは、サイトがユーザーのデバイス上のファイルを安全に読み書きできるようにするための最新のブラウザAPIだ。OPFSを使用することで、ブラウザを閉じてもローカルでデータを保持することができる。
当初は、シンプルな方法でWASM版SQLite3の導入を検討していたという。ブラウザのメインスレッドとは別に、バックグラウンドでJavaScriptを実行する「Web Worker」の仕組みを用いて、Notionを開いているブラウザタブごとに1つのWeb Workerを設け、各Web Workerでデータをキャッシュする手法だ。
その手法の実現にOPFSを使用しており、その実装を「sqlite3_vfs」(SQLite3の仮想ファイルシステムのインタフェース)と、SQLite3.43で追加された「SyncAccessHandle Pool VFS」のどちらを通じて行うかを検討した。これらの実装では次の3つの課題が生じた。
- 「クロスオリジン分離」の問題:sqlite3_vfsを通じてOPFSを使用するには、クロスオリジン分離が必要だった。Webインフラストラクチャのさまざまな機能を実現するために多くのサードパーティースクリプトに依存しているNotionの場合、クロスオリジン分離を果たすためには、スクリプトの提供元にコードの変更を依頼する必要があり、非現実的だった
- データの不整合:sqlite3_vfsを通じてOPFSを使用する手法を一部のユーザーに対して有効化した結果、ページ上で誤ったデータが表示されるなど深刻なバグが生じた。複数のタブを開いている際、各タブのWeb Workerが同時にファイルに対して書き込み処理を同時実行することによるデータの不整合が起きていた。応急処置的なアプローチも試みたが、再び本番環境で有効化することは難しくなった
- 1つのタブでしか実行できない:SyncAccessHandle Pool VFSを使用する場合、sqlite3_vfsで起きたデータ不整合の問題は起きないものの、1つのタブでしかNotionを実行できないという問題があった。複数タブでもキャッシュの恩恵を受けるという目的を果たせないため、この手法も適用できなかった
そこで同社は、「wa-sqlite」プロジェクトの開発者であるロイ・ハシモト氏が提唱した「一度に1つのタブだけがSQLiteにアクセスし、他のタブがSQLiteクエリを実行できるようにするアプローチ」を参考に、解決策となるアーキテクチャを検討したという。
このアーキテクチャではWeb Workerに加えて、複数のタブやウィンドウ間からアクセスできる「SharedWorker」と、複数のタブやスクリプトが同じリソースにアクセスしないように管理する「Web Lock API」を活用している。
各タブがWASM版SQLite3に書き込む専用のWeb Workerを持ち、常にアクティブなタブだけがWASM版SQLite3にアクセスできるよう、SharedWorkerがアクティブタグを管理する。アクティブタグが閉じられると、SharedWorkerは新しいアクティブタブを選択する。SharedWorkerがアクティブタブを検出するために、Web Lock APIを活用しているという。
このアーキテクチャにより、実装上の課題を解決できると判断し、SyncAccessHandle Pool VFSと組み合わせてWASM版SQLite3を導入したという。
WASM版SQLite3導入の教訓
Notion Labsは、パフォーマンス改善を目的にWASM版SQLite3を導入する上で直面した課題を踏まえ、次のように教訓を共有している。
- OPFSは同時実行のための処理を標準で提供していない。開発者はこれを踏まえた上で、設計を検討する必要がある
- Web WorkerとSharedWorkerにはそれぞれ異なる機能があり、必要に応じてこれらを組み合わせることで有用なケースがある
- 2024年春の時点で、高度なWebアプリケーションで完全なクロスオリジン分離を実装することは容易ではなく、特にサードパーティーのスクリプトを使用している場合には困難だ
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
ブラウザ内でPostgresのWASM版を利用できる「postgres.new」を発表 Supabase
Supabaseは、AI支援を利用しながら、ブラウザ内で直接動作する「Postgres」データベースを即座に幾つでも起動し、サンドボックスとして使用できる「postgres.new」を発表した。スクリプト言語TypeScriptでWebAssembly――「AssemblyScript」を体験する
第2回では、TypeScriptでWebAssemblyプログラムを開発できるAssemblyScriptを紹介します。差異こそありますがTypeScriptの構文を使ってコードを書けるので、フロントエンドに慣れた開発者にとってはWebAssemblyのための入りやすい選択肢と言えます。「WebAssembly」は次世代のJava、Node.jsになる?――「Wasmコンテナ」をKubernetesで動かす
Kubernetesやクラウドネイティブをより便利に利用する技術やツールの概要、使い方を凝縮して紹介する連載。今回は、最近注目されている「WebAssembly」について復習しながら、WebAssemblyのアプリケーションをKubernetesで試す方法を紹介する。