🚀

WebAssembly の利用シナリオを調べる

2020/12/13に公開1

先日 弊社 CTO が既存の処理を書きやすくしたり、扱いやすくしたりする技術は日々登場し、これらを学ぶことも重要だが、数年に一度登場するこれまでできなかったことができるようになる技術には特に注目すべきだという話をしていました。

その具体例として WebAssembly (以降 wasm)でパフォーマンス向上させることで実現した Google Meet のぼかし機能 (なぜGoogle Meetの背景ぼかしが最強なのか(一般公開版)) や wasm を用いたサーバレス基盤 Compute@Edge (Edge で 圧縮処理や認証などのこれまでできなかったことが CDN の Edge でできるようになる) を挙げ、wasm はこれまでできなかったことを実現する技術であり注目すべきとのことでした。

かなり納得しました。自分自身いろんな技術を追いかけていますが、確かに既存のものを少し便利にしたのものがほとんどかもしれません。(もちろんそうして少しつづ進歩していくのがソフトウェアの良い点だと思いますが)しかし、本質的に不可能を可能にする技術が生まればそれを先進的に試さない手はありません。

一応私も去年のアドベントカレンダーでWASI (WebAssembly system interface) を Wasmtime と Node.js で試すというものをやってみたりして wasm には前から注目しています。Web エンジニアとしてこんなにワクワクする領域も少ないと思います。しかし、現状プロダクションで wasm に置き換えたり、これを使ってサービスを作ったりはできていません。

そこで今回は改めて wasm でできるようになること or これまでネイティブでしか実用性の観点から実現できなかったことが wasm を使ってブラウザでも実現できるようになることはなんなのか調べてみました。

本稿はそれらのまとめと、使いどころがあるかもしれないと考えた 3 つの wasm ライブラリについて紹介します。wasm とは何かなどについては WASI (WebAssembly system interface) を Wasmtime と Node.js で試すで説明しているので手前味噌ですが、そちらを先に読んでいただけると幸いです。(もちろん公式を先に読んでいただくと良いと思いますが…)

2020 wasm

考えられる誤解

wasm に関して考えられる誤解として wasm が全てのブラウザで実行される JavaScript にとってかわる存在であるというものがあります。ですが、ネイティブで実行されるからといってなんでもかんでも wasm で書けばいいというものではありません。これは JavaScript の VM (Chrome で言えば v8) がコードの実行前と実行中にあらゆる最適化がほどこされているため、主な Web のタスク (e.g. DOM 操作)などにおいては wasm と比較しても十分高速に実行されるためです。ではどのようなときに利用すると wasm を有効利用できるのでしょうか。

wasm の利用シナリオ

実際のところはケースバイケースで計測してみなければわからない部分もあるようですが、具体的に考えると以下の表のような使い分けが考えられます。

シナリオ 推奨
計算量の多いアルゴリズム wasm
DOM 操作 JS
ゲーム 計算量の多い箇所のみ wasm
WebGL API を呼び出す量により異なる。両方考えうる
画像、ビデオ編集 wasm
暗号 wasm
Websites, Blogs, ... JS

参考 : Frequently asked questions

加えて wasm はパフォーマンスの他に移植生も考慮されて設計されています。これによって C++ などでクライアント向けに実装された SDK なども Web に移植できる可能性も生まれます。他にもゲームの SDK, 画像コーデック, 機械学習のモデル、言語ランタイムなども対象にできるでしょう。
とはいえ現実世界で使えているのか Google みたいなトップクラスの技術力の会社だけじゃない?と思われるかもしれません。次はプロダクションの例を調べてみます。

プロダクションでの導入例

Web アプリではまだそこまで実装例は多くないですが、着実にプロダクションでの使用例は年々増えているようです。Google は Meet だけでなく Earth でもプロダクション投入しているようで流石ですね…

参考: Welcome to the World of WebAssembly!

wasm を生成できる言語は C/C++/Rust などの数多の言語がありますが、基本的には JS から wasm の API を呼び出すためアプリケーションを実装する場合、ライブラリとして実装されたものを呼び出す場合が多いと思われます。ですので次はライブラリを探してみます。

気になったライブラリ

主に GitHub の wasm topics からざっくり三つ選んでみました。それぞれ以下の用途のライブラリです。それぞれみて行きます。

  • sql.js : SQLite をブラウザで使えるライブラリ
  • photon : 画像処理ライブラリ
  • FFMPEG : FFmpeg を wasm に移植したもの

sql.js

その名の通り SQLite が wasm によって移植されてたもので、ブラウザ上で SQL を使用することを可能にしたライブラリです。
複雑な集計処理などを実装する場合は、ユーザーに SQL での集計処理を擬似的にサポートする際。また、プライバシーでデータ保護のニーズも高まっているのでそもそもサーバーにデータ送りたくないがクライアントサイドでそれなりに複雑なデータを扱いたいという場合にも使用できそうです。
当然、データの永続化はされませんが、indexedDB などに格納するなどして半永続化するなどの使い道もあるのではないかと考えました。
以下にデモも存在しており、テーブルとカラムがそれぞれ JS の配列にマッピングされ使用することができます。

demo: https://sqljs-react-demo.netlify.app/

Photon

ブラウザで使用できる高速な画像処理ライブラリです。こういった処理は従来 OpenCV や ImageMagic などがよく用いられてきたと思いますが、Photon はブラウザ上でも画像の編集(色フィルター、リサイズ、クロップ、テキストの追加、効果)を実行することが可能です。
以下のでものようにすでに実装されているフィルター処理などを組み合わせて利用することができます。

demo: https://silvia-odwyer.github.io/photon/demo.html

FFMPEG.wasm

このライブラリも FFmpeg が wasm によって移植されてたもので、ブラウザ上で 音声・動画をエンコード及び編集することを可能にするライブラリです。
2 分程度の動画を試しに mp4 を H264 に圧縮させてみましたが、45秒 ほどで実行することができました。他にも当然ですが FFempeg ができるリサイズや他の形式に変換するなどの処理もブラウザで実現できるようになります。動画をアップロードせずとも変換をさせることができるので通信を発生させないメリット、またはサーバーの計算リソースを節約するメリットなどがありそうです。圧縮してアップロードすれば、総合的な通信量も減らすことができます。

ちなみにマシン環境は以下です。
MacBook Pro 2017, 2.3 GHz, 16GB

demo: https://ffmpegwasm.github.io/

まとめ

  • 適材適所なシナリオで wasm を利用する。
  • ブロダクションでも十分利用される実績は出てきている
  • sql.js photon ffmpeg.wasm の紹介

wasm の利用シナリオをそれなりの数、頭に入れることができました。wasm は十分に導入を検討してもいいフェーズにきていると思います。つい先日も WebAssembly で Markdown エディタを作って2倍速を実現できたとの記事 がzenn で話題になりましたが、wasm をどのようにすれば利用できるか考えていないと実現できないアイデアだと思います。素晴らしすぎます。

ところで、ここでふと考えたのですが、ソフトウェアにおいて不可能を可能にする技術というわかりやすい線引きをするのは実は難しいのではないかと思いました。これまで計算やストレージのリソースが増大していけば自ずと、それを生かすための技術がモバイルや ML といった形で実現してきました。これらすべて以前からやろうと思えばできましたが、実用的な速度で動かなかっただけです。この実用的な速度を出せるか出せないかという曖昧なところにエンジニアリングで解決できれば、今この世にないものを作れるのかもしれない。そのような考えに至りました。エンジニアとして経験を積むと、動くコードを書くのはなんとかハードルを越えられるようになってきたと思うようになりましたが、速度にこだわったり、適切な設計を考案したりすることはまだまだと思います。エンジニアとして次のステージに行くためにはこれら2点が主な課題かもしれません。来年はなんらかの形で wasm を実用的に使いアドカレでドヤ顔できるようにしたいと思います。

本稿が wasm をこんなシナリオで自社のサービスに組み込めるのではいか、サービスを作れるのではないかという読者のアイデアの創出に少しでも役立てば幸いです!!

以上

明日は pakio さんの BigQueryのQuery too complexをtemp tableで回避する です!お楽しみに!

参考

Discussion

こーのいけこーのいけ

こんにちは、記事が参考になったようで良かったです。

個人的にはWasmの利用シナリオで「音声」も割と普及が進んでいる気がしています。Web Audio APIで扱いやすいので画像処理よりも先行していると思います。MeetなどのWeb会議では主に雑音抑制、エコーキャンセルなどで使われているような感じがあります。ライブラリとしてもEssentia.jsなどがあります。