はじめに
前回の記事では、Rust と WebAssembly(WASM)を使って「Hello」を表示する最小構成のデモを作成しました。 続編となる今回は、Rust/WASM の高速性を体感できるデモを作ってみます。
JavaScript と Rust/WASM の両方で「大量の配列の合計」を計算し、処理速度を比較します。 前回の知識をそのまま活かせる内容になっているので、ぜひ一緒に進めてみてください。最終的には意外な結果でした。
今回のゴール
- JavaScript で 1,000 万件の配列を生成する
- Rust/WASM に配列を渡して合計値を計算する
- JS と WASM の処理速度を比較する
- Rust/WASM が得意とする「数値計算」の強みを体感する
開発環境(前回と同じ)
今回も以下の環境を前提に進めます。
- VS Code
- Rust(rustup)
- wasm-pack
- ロリポップのレンタルサーバー(静的ファイル配置)
前回と同じ環境で問題ありません。
Rust プロジェクト作成(ローカル PC / VS Code)
ローカルの C:\rust\ の中で以下を実行します。
cargo new wasm-sum --lib
cd wasm-sum次に Cargo.toml を編集します。
[package]
name = "wasm-sum"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "0.2"Rust コード(lib.rs)
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn sum(values: Vec<f64>) -> f64 {
values.iter().sum()
}
解説
- JS の
Float64Arrayが Rust のVec<f64>に自動変換されます - Rust 側では普通の Vec として扱えます
.iter().sum()は Rust の高速イテレータ- 計算は WASM 側で行われるため、JS より高速になりやすいです
Rust の Vec(ベクター) は、Rust で最もよく使われる 可変長の配列(動的配列) です。 JavaScript でいうと Array に近い存在です
wasm-pack build(ローカル PCでのビルド)
wasm-pack build --target webローカルに pkg/ フォルダが生成されます。
ローカルに pkg/ フォルダが生成され、以下のファイルができます。
wasm-sum/pkg/
wasm_sum.js
wasm_sum_bg.wasm
wasm_sum_bg.wasm.d.ts
wasm_sum.d.tsサーバー側のフォルダ構成(wasm.kajiblo.com)
ローカルで生成された pkg/ をサーバーにアップロードします。
最終的にサーバー側は次のようになります。
/wasm/
├── index.html
├── hello/
├── hello_name/
├── sum/ ← 新規追加
│ └── index.html
├── pkg/ ← hello 用(既存)
└── pkg_sum/ ← sum 用(今回追加)
├── wasm_sum.js
├── wasm_sum_bg.wasm
├── wasm_sum_bg.wasm.d.ts
└── wasm_sum.d.ts
Rust/WASM は プロジェクトごとに pkg が生成されるため、 デモごとに pkg を分ける構成にしました。
sum/index.html
以下を /wasm/sum/index.html としてアップロードします。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Rust/WASM 高速計算デモ</title>
</head>
<body>
<h1>Rust/WASM 高速計算デモ(配列の合計)</h1>
<button id="run">計測スタート</button>
<pre id="output"></pre>
<script type="module">
import init, { sum } from "../pkg_sum/wasm_sum.js";
async function run() {
await init();
const output = document.getElementById("output");
const size = 10_000_000;
const arr = new Float64Array(size);
for (let i = 0; i < size; i++) arr[i] = Math.random();
const t1 = performance.now();
let jsSum = 0;
for (let i = 0; i < size; i++) jsSum += arr[i];
const t2 = performance.now();
const t3 = performance.now();
const wasmSum = sum(arr);
const t4 = performance.now();
output.textContent =
`JS 合計: ${jsSum}\n` +
`JS 時間: ${(t2 - t1).toFixed(2)} ms\n\n` +
`WASM 合計: ${wasmSum}\n` +
`WASM 時間: ${(t4 - t3).toFixed(2)} ms\n`;
}
document.getElementById("run").onclick = run;
</script>
</body>
</html>
/wasm/index.html に sum へのリンクを追加
<a href="./sum/" class="card">
<div class="card-title">高速計算デモ(sum)</div>
<div class="card-desc">1,000 万件の配列を Rust/WASM で高速に合計</div>
</a>
追加したTop画面

デモ画面

実行結果:JS のほうが速い?
実際に動かしてみると、JS のほうが速い結果になることがあります。 これは誤りではなく、今回のデモの構造上「JS が有利な条件」になっているためです。
JS が速い理由
1. JS → WASM のデータコピーが重い
Float64Array を WASM に渡すとき、全件コピーが発生します。 1,000 万件だとコピーだけで相当な時間がかかります。
2. JS の JIT 最適化が「単純なループ」に強い
今回の JS の処理は V8 が最適化しやすい典型的なパターンです。
for (let i = 0; i < size; i++) jsSum += arr[i];この場合、JS はほぼ C 並の速度を出します。
3. WASM 関数呼び出しコストがある
JS → WASM の境界をまたぐため、呼び出しコストが JS より高くなります。
WASM が本領を発揮するのはどんなとき?
- ソート(O(n log n))
- 行列計算
- 画像処理(ピクセル操作)
- 暗号処理(SHA-256)
- 物理演算
こうした 計算が重い処理では WASM が圧倒的に速くなります。
また、データを WASM 内に置きっぱなしにして コピーをなくす構造にすると、さらに高速になります。
まとめ
今回の記事では、前回の Hello デモから一歩進んで、Rust/WASM の高速性を体感できるデモを作成しました。
- Rust/WASM は大量データの計算で JS より高速になることが多い
- ただし今回のように「JS → WASM に大量コピーする構造」では JS が有利
- Vec と TypedArray の連携を学べた
- WASM が本領を発揮するのは、より重い計算や WASM 内で完結する処理
次回は、ソート や 画像処理 など、WASM がより速くなるデモにも挑戦したいと思っています。

コメント