目次
ブラウザでPDFを編集したり、ビデオを変換したり、機械学習モデルを動かしたりする体験が普及してきた。これを可能にしているのがWebAssembly(WASM)だ。「なぜブラウザでネイティブアプリ並みの速度が出るのか」を理解するには、WASMの仕組みを知る必要がある。
JavaScriptだけでは足りなかった
JavaScriptはWebのプログラミング言語として成功したが、計算集約型のタスクには限界がある。
// 大量の数値計算:JSは遅い
function sumArray(arr) {
let sum = 0;
for (let i = 0; i < arr.length; i++) {
sum += arr[i]; // 動的型チェックが毎回発生
}
return sum;
}
JavaScriptの動的型システム(変数の型が実行時まで確定しない)は柔軟だが、型チェックのオーバーヘッドが積み重なる。1,000万回のループでは顕著な差になる。
WebAssemblyとは
WebAssemblyはブラウザ上で動作するバイナリ命令形式だ。
C/C++/Rust/Go のソースコード
↓ コンパイル
WebAssembly バイナリ(.wasm)
↓ ブラウザで実行
ネイティブに近い速度
WASMはJavaScriptの「置き換え」ではなく「補完」だ。計算集約型の処理をWASMに任せ、DOMの操作やUIはJavaScriptが行う。
WASMの技術的な特徴
バイナリ形式で高速ロード
WASMはコンパクトなバイナリ形式(.wasm)で配信される。テキストベースのJavaScriptより小さく、パースが速い。
型付きの低レベル命令
WASMの命令セットは型が明確に決まっている(i32, i64, f32, f64)。実行時の型チェックが不要で、CPUのネイティブ命令に近い形でコンパイルできる。
;; WASMのテキスト表現(WAT形式)
(module
(func (export "add") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add
)
)
サンドボックス実行
WASMはブラウザのサンドボックス内で動作し、メモリやシステムリソースへの直接アクセスが制限されている。セキュリティは維持される。
実際の速度差
// ベンチマーク例(概念的)
// フィボナッチ数列の計算(n=45)
// JavaScript: 約7秒
function fib(n) {
if (n <= 1) return n;
return fib(n-1) + fib(n-2);
}
// WASM (Rustコンパイル): 約0.5秒
// → 約14倍高速
実際の差はタスクによるが、数値計算では2〜10倍程度の高速化が一般的だ。
RustからWASMを作る
Rustは現在最もWASMとの相性が良い言語の一つだ。
// src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[wasm_bindgen]
pub fn sum_array(arr: &[f64]) -> f64 {
arr.iter().sum()
}
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a = 0u64;
let mut b = 1u64;
for _ in 2..=n {
let c = a + b;
a = b;
b = c;
}
b
}
}
}
# ビルド
wasm-pack build --target web
# 生成物
pkg/
├── my_lib_bg.wasm # WASMバイナリ
├── my_lib.js # JSラッパー
└── my_lib.d.ts # TypeScript型定義
// JavaScriptから使う
import init, { add, fibonacci } from './pkg/my_lib.js';
async function main() {
await init(); // WASMを初期化
console.log(add(3, 5)); // 8
console.log(fibonacci(45)); // 1134903170
}
main();
ブラウザでのAI推論——WASMの最前線の応用
LLMや画像認識モデルをブラウザで動かす試みが広がっている。
ONNX Runtime Web
ONNXはAIモデルの標準フォーマット。ONNX Runtime Webを使うとブラウザでモデルを実行できる。
import * as ort from 'onnxruntime-web';
async function runInference(imageTensor) {
// WASMバックエンドでモデルを読み込み
const session = await ort.InferenceSession.create(
'./model.onnx',
{ executionProviders: ['wasm'] } // WASMで実行
);
const feeds = { input: imageTensor };
const results = await session.run(feeds);
return results.output.data;
}
Transformers.js
HuggingFaceのTransformers.jsは、NLPモデルをブラウザで動かすライブラリ。内部でWASMを使う。
import { pipeline } from '@xenova/transformers';
// モデルはブラウザにダウンロード・WASMで実行
const classifier = await pipeline('sentiment-analysis');
const result = await classifier('I love WebAssembly!');
// [{ label: 'POSITIVE', score: 0.999 }]
// 音声認識(Whisper)もブラウザで動く
const transcriber = await pipeline('automatic-speech-recognition', 'openai/whisper-tiny');
const output = await transcriber('audio.wav');
WebGPUとの組み合わせ
WASMはCPUで実行されるが、WebGPU APIを使うとGPU計算も可能になる。大規模モデルの推論はWebGPUがより高速だ。
// WebGPU バックエンドを優先(対応ブラウザのみ)
const session = await ort.InferenceSession.create('./model.onnx', {
executionProviders: ['webgpu', 'wasm'], // 順に試みる
});
WASMが使われている主なプロダクト
| プロダクト | WASMの用途 |
|---|---|
| Figma | レンダリングエンジン |
| Adobe Photoshop Web | 画像処理 |
| Google Earth | 3D地図レンダリング |
| FFmpeg.wasm | ブラウザ動画変換 |
| SQLite.wasm | ブラウザ内データベース |
| whisper.wasm | 音声認識(オフライン) |
WASI——ブラウザ外でのWASM
WASI(WebAssembly System Interface)はWASMをサーバーサイド・組み込みデバイスで動かすための規格だ。
# WasmtimeでWASMを実行(ブラウザ不要)
wasmtime my_program.wasm
# Docker + WASM(実験的)
docker run --runtime=io.containerd.wasmtime.v1 my-wasm-image
「一度書けばどこでも動く(Write Once, Run Everywhere)」をJVMより安全・軽量に実現する可能性がある。
まとめ
WebAssemblyはJavaScriptを置き換えるのではなく、ブラウザの計算能力を大幅に拡張する技術だ。
- 仕組み: バイナリ形式・型付き命令・サンドボックス実行
- 速度: 数値計算でネイティブの50〜80%程度の速度を達成
- 言語: Rust・C++・Go などからコンパイル可能
- AI応用: ONNX Runtime Web・Transformers.js でブラウザ推論が実現
- WASI: ブラウザ外(サーバー・組み込み)にも展開中
エッジでのAI推論(プライバシー保護・低レイテンシ・オフライン動作)のニーズが高まる中、WASMはブラウザAIの核心技術として今後さらに重要になっていく。
免責事項 — 掲載情報は執筆時点のものです。料金・機能は変更される場合があります。最新情報は各公式サイトをご確認ください。