ツリーシェイキング、園芸学的に誤解を招くアルゴリズム (2023)
(wingolog.org)WebAssemblyの限界とTree-shakingの重要性
-
WebAssemblyは多くの関心と期待にもかかわらず、Webでは限定的な成功しか収めていない
- Photoshopのような成功事例もあるが、全体的にはWebAssemblyを活用したプロジェクトは多くない
- 特にDOMを多用するアプリではWebAssemblyは適していない
- JavaScriptとWebAssemblyのプログラミングモデルの違いが主な原因のひとつ
-
WebAssemblyはCやRustのような言語以外では大きく成功していない
- C#のような言語はガベージコレクタなどのランタイムを一緒に提供しなければならない不便さがある
- ただし参照型とガベージコレクションをサポートするWebAssemblyの新機能がまもなく導入される予定で、状況の改善が期待される
コンパイラのコード最適化能力がWebAssembly成功の鍵
-
WebAssemblyがWebで成功するには、コンパイラが小さく効率的なコードを生成できなければならない
- 数キロバイト程度の小さなファイルサイズを維持することが重要
- そうでなければ、誇大宣伝や特定のユーザーベースに依存せざるを得ない
-
JavaScriptの世界では、バンドラなどを通じてコードサイズ最適化が行われている
- Tree-shakingは、プログラムで実際に使用される関数とデータ型だけを含める手法
-
Tree-shakingは、園芸学的にもアルゴリズム的にも不適切な比喩ではあるが、広く使われている用語
他の言語におけるTree-shakingの現状
-
GoやPythonなどランタイムが重い言語では、まだTree-shakingが最適化されていない
- 最も単純なGoプログラムでも、WebAssemblyにコンパイルすると2MB以上のサイズになる
- PythonのPyodideも約20MBのファイルをダウンロードしなければならない
-
サーバー環境ではバイナリサイズが大きな問題にならないため
- モバイルなど制約のある環境向けには、MicroPython、TinyGoなどの軽量化されたツールチェーンが別途開発されることもある
-
Web環境向けの言語実装は既存のものと違わざるを得ない
- DOMと相互作用すること自体が特異な環境だから
- ClojureScriptは、Clojureとの違いを別途文書化している
Tree-shakingアルゴリズムに関する議論
-
著者が開発中のHoot Schemeコンパイラは、現在およそ70KBのWasmコードを生成している
- 関数(プロシージャ)定義だけを含めるのは比較的容易
- しかし、以下のようないくつかの難しい点がある
-
letrec*評価モデルでは、束縛が再帰的でありながら順序もあるため、コンパイラが解析しにくい- レコード型の場合、vtableコールバックが多くのコードを残してしまう
-
displayのように多相性の高い関数を使うと、関連する多くのコードが含まれるwrite-stringなど具体的な関数を使うほうがよい
-
最適なTree-shakingのためには、flow analysisが必要
displayにbitvector引数が渡されないと分かれば、関連コードを除去できる
-
Pythonでは、動的ディスパッチ、
__getattr__などの動的機能のためさらに難しい- Pythonのモジュール構造もTree-shakingを複雑にする要因
要約
- GCサポートにより、WebAssemblyでJavaScript以外の言語によるDOMプログラミングが可能になる
- しかし成果物のサイズを十分小さくするには、各言語ツールチェーンへの相当な投資が必要
- Tree-shakingアルゴリズムを適用した別個のツールチェーン開発や標準ライブラリ最適化などが求められる
GN⁺の見解
-
WebAssemblyがGCをサポートすることで、Web開発にさまざまな言語を使えるようになったが、既存言語のツールチェーンをそのまま持ち込むには難しさが多いように見える。Web環境に特化した言語実装と最適化手法が開発される必要がありそうだ。
-
Tree-shakingが動的型付け言語でうまく機能するには、静的解析が不可欠だと思われる。だがPythonのような言語は動的機能が多く、簡単ではなさそうだ。いっそ最初から静的解析に有利な言語を新たに作るのも方法かもしれない。
-
HootやTinyGoのような実験的プロジェクトはよい参考になりそうだ。だがこうしたプロジェクトを実際の製品に適用するには、まだ時期尚早かもしれない。段階的に改善していくしかなさそうだ。
-
パフォーマンスにそれほど敏感でなく、迅速な開発が重要なプロジェクトなら、Pyodideのようなものを使ってみる価値はありそうだ。だがユーザー体験を重視する製品なら、現時点ではJavaScriptが最善の選択に思える。
-
WebAssembly自体にTree-shakingのような機能を入れることも考えられそうだ。だが言語ごとに要件が異なるため簡単ではないだろう。またTree-shakingをうまく支援する言語が登場すれば、むしろその言語でコーディングするほうが得かもしれない。WebAssemblyとプログラミング言語の役割分担がどうなっていくのか興味深い。
1件のコメント
Hacker Newsの意見
要約すると次のとおりです:
floatの代わりに固定小数点演算を使用HashMapの代わりにVecを使用talc)を使用rand、fxhashのみを使用)mainエントリポイントから探索し、到達可能なコードだけを最終バイナリに含める。