JavaScript で配列を走査する 4 つの方法:for、for-in、for-of、forEach()
- 2021年6月12日
- Liu, An-Chi 劉安齊
Code makes the world a better place
まずは WebAssembly とは何か、そしてなぜ必要なのかから整理しましょう。
いまや Web 技術はあらゆる場面に浸透しています。人々は 1 日のうち何時間もインターネットを利用し、さまざまなサービスを享受しています。多くのアプリケーションが Web に移行し、デスクトップアプリやモバイルアプリでも Web アプリ(Web App)やハイブリッドアプリ(Hybrid App)を採用するケースが増えています。言い換えるなら、Web 技術が世界を支配していると言っても過言ではありません。
Web の中心にある言語は JavaScript(JS)です。ブラウザや JS エンジンの進化によって性能は向上してきましたが、最適化には限界があります。JS はインタプリタ型言語であり、実行時にコードを 1 行ずつ読み込みながらコンパイルして実行します。このモデルは、C++ のようなコンパイル型言語より遅くなりがちです。
では、なぜ Web で C++ のようなコンパイル型言語をそのまま使わないのでしょうか。事前にコンパイルして配布する場合、生成物(実行ファイル)が大きくなりやすく、ブラウザへ配信するネットワーク転送に時間がかかります。逆に、ブラウザが受け取ってからコンパイルする場合は、コンパイル完了まで待つ必要があり、それも時間がかかります。JS はソースが比較的小さく、転送時間を抑えやすい上に、ブラウザが逐次的にコンパイルして「先にコンパイルできた部分から実行する」こともできるため、体感の遅さを抑えやすいという事情があります。
それでも、JS の性能には上限があります。そこで「ブラウザ上でより高速に動作させたい」という要求から誕生したのが WebAssembly(WASM)です。WASM は低レベルでアセンブリに近い形式であり、C++ や Rust のようなネイティブ(Native)コードに近い性能を狙えます。Web 開発では JS と WASM を組み合わせて使います。イメージとしては、一般的なアプリのロジックは JS で動かしつつ、計算負荷が高い部分を事前にコンパイルされた WASM に置き換えることで性能を向上させます。つまり、JS の「起動が速い」という利点と、WASM の「重い計算を高速に実行できる」という利点を両取りするアプローチです。
以降では、JS と WASM を組み合わせた開発方法を紹介します。
Continue reading
Emscripten は C/C++ を WebAssembly に変換できるツールです。裏側では LLVM を経由して変換し、Pthread の変換もサポートしています。Pthread は JavaScript の Web Worker と WebAssembly に変換されます。さらに OpenGL を WebGL に変換することもでき、ブラウザ上でネイティブに近い性能でプログラムを動かせます。
本記事の焦点は、Pthread を Web Worker + WebAssembly に変換する部分です。実際に例題プログラムを用意して変換してみます。ただ、良いテストプログラムを見つけるのは簡単ではないので、変換テスト用に π を計算する Pthread の平行プログラムを書きました。
まずは Emscripten で Pthread を JS に変換する方法を紹介します。公式ドキュメント通りに進める過程でいくつか落とし穴に遭遇したので、同じ罠に落ちないように記録しておきます。その後、(1) ネイティブ C (2) Emscripten が生成した JS/WASM (3) JavaScript で直接書いた Web Worker の 3 ケースで性能差を分析します。
Continue reading