- Published on
WebAssembly完全ガイド2025:ブラウザを超えて — WASI、Component Model、サーバーサイドWasm
- Authors

- Name
- Youngju Kim
- @fjvbn20031
目次(もくじ)
1. WebAssemblyとは何(なに)か
WebAssembly(Wasm)は、スタックベースの仮想(かそう)マシン向(む)けバイナリ命令(めいれい)フォーマットである。元々(もともと)はWebブラウザでネイティブに近(ちか)いパフォーマンスを提供(ていきょう)するために設計(せっけい)されたが、現在(げんざい)はブラウザを超(こ)えてサーバー、エッジ、IoTまで拡張(かくちょう)されている。
1.1 Wasmの中核(ちゅうかく)特性(とくせい)
| 特性 | 説明(せつめい) | 意味(いみ) |
|---|---|---|
| バイナリフォーマット | コンパクトなバイナリエンコーディング | 高速(こうそく)転送(てんそう)、高速デコード |
| スタックマシン | スタックベースの命令実行 | シンプルで効率的(こうりつてき)な実行モデル |
| 線形(せんけい)メモリ | 連続(れんぞく)したバイト配列(はいれつ) | 安全(あんぜん)なメモリアクセス、サンドボックス |
| 型安全(かたあんぜん) | 強い型システム | コンパイル時検証(けんしょう)、ランタイム安全 |
| 移植性(いしょくせい) | アーキテクチャ非依存(ひいぞん) | x86、ARM、RISC-Vどこでも実行 |
| サンドボックス | 隔離(かくり)された実行環境(かんきょう) | ホストシステム保護(ほご) |
1.2 Wasmの歴史(れきし)
2015: WebAssemblyプロジェクト発表(W3C)
2017: 4大ブラウザでWasm 1.0サポート
2019: WASI初期提案(非ブラウザWasm)
2020: Wasm 1.0がW3C公式勧告
2021: Component Model提案、Fermyon創立
2022: Docker+Wasm技術プレビュー、WASI Preview 1
2023: WASI 0.2安定化、Component Model成熟
2024: GC proposal実装、主要ランタイム最適化
2025: WASI 0.2 Production-ready、サーバーサイドWasm本格採用
1.3 Wasmバイナリ構造(こうぞう)
Wasmモジュール構造:
+------------------+
| Magic Number | 0x00 0x61 0x73 0x6D ("\0asm")
| Version | 0x01 0x00 0x00 0x00 (v1)
+------------------+
| Type Section | 関数シグネチャ定義
| Import Section | 外部関数/メモリインポート
| Function Section | 関数インデックス
| Table Section | 間接呼び出しテーブル
| Memory Section | 線形メモリ定義
| Global Section | グローバル変数
| Export Section | 外部公開関数/メモリ
| Start Section | 自動実行関数
| Element Section | テーブル初期化
| Code Section | 関数本体(バイトコード)
| Data Section | メモリ初期データ
+------------------+
1.4 WAT(WebAssembly Text Format)
Wasmのテキスト表現(ひょうげん)形式(けいしき)であるWATを理解(りかい)すると、内部(ないぶ)動作(どうさ)を把握(はあく)できる。
;; 二つの数を足すシンプルなWasmモジュール
(module
;; 関数型定義
(type $add_type (func (param i32 i32) (result i32)))
;; 関数実装
(func $add (type $add_type) (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add
)
;; 線形メモリ(1ページ = 64KB)
(memory (export "memory") 1)
;; 関数エクスポート
(export "add" (func $add))
)
2. ブラウザWasm
2.1 様々(さまざま)な言語(げんご)からWasmへコンパイル
Rust - Wasmの第一級(だいいっきゅう)市民(しみん)
// lib.rs - RustからWasmへ
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
if n <= 1 {
return n as u64;
}
let mut a: u64 = 0;
let mut b: u64 = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
#[wasm_bindgen]
pub struct ImageProcessor {
width: u32,
height: u32,
pixels: Vec<u8>,
}
#[wasm_bindgen]
impl ImageProcessor {
#[wasm_bindgen(constructor)]
pub fn new(width: u32, height: u32) -> ImageProcessor {
ImageProcessor {
width,
height,
pixels: vec![0; (width * height * 4) as usize],
}
}
pub fn grayscale(&mut self) {
for chunk in self.pixels.chunks_exact_mut(4) {
let gray = (0.299 * chunk[0] as f64
+ 0.587 * chunk[1] as f64
+ 0.114 * chunk[2] as f64) as u8;
chunk[0] = gray;
chunk[1] = gray;
chunk[2] = gray;
}
}
pub fn pixels_ptr(&self) -> *const u8 {
self.pixels.as_ptr()
}
}
# Rust -> Wasm ビルド
wasm-pack build --target web
C/C++ - Emscripten
// image_filter.c - CからWasmへ
#include <emscripten.h>
#include <stdint.h>
EMSCRIPTEN_KEEPALIVE
void apply_blur(uint8_t* pixels, int width, int height) {
uint8_t* temp = (uint8_t*)malloc(width * height * 4);
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
for (int c = 0; c < 3; c++) {
int sum = 0;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
sum += pixels[((y+dy)*width + (x+dx))*4 + c];
}
}
temp[(y*width + x)*4 + c] = sum / 9;
}
temp[(y*width + x)*4 + 3] = pixels[(y*width + x)*4 + 3];
}
}
memcpy(pixels, temp, width * height * 4);
free(temp);
}
2.2 JavaScriptとの相互(そうご)運用(うんよう)
// Wasmモジュールのロードと使用
async function initWasm() {
// 方法1: fetch + instantiate
const response = await fetch('module.wasm');
const bytes = await response.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes, {
env: {
// ホスト関数をWasmに提供
log_value: (value) => console.log('Wasm says:', value),
get_time: () => Date.now(),
}
});
// Wasm関数呼び出し
const result = instance.exports.add(10, 20);
console.log('Result:', result); // 30
// 線形メモリアクセス
const memory = new Uint8Array(instance.exports.memory.buffer);
return instance;
}
// 方法2: wasm-bindgen (Rust)
import init, { fibonacci, ImageProcessor } from './pkg/my_wasm.js';
async function main() {
await init();
console.log('fib(40):', fibonacci(40));
const processor = new ImageProcessor(800, 600);
processor.grayscale();
}
2.3 ブラウザWasmの主要(しゅよう)ユースケース
| ユースケース | 例(れい) | パフォーマンス向上(こうじょう) |
|---|---|---|
| 画像(がぞう)/動画処理 | Photoshop Web、FFmpeg.wasm | JS比10-50倍 |
| ゲームエンジン | Unity WebGL、Unreal Engine | ネイティブの70-90% |
| コーデック/圧縮(あっしゅく) | AV1デコード、Brotli圧縮 | JS比5-20倍 |
| 暗号化(あんごうか) | SHA-256、AES演算 | JS比3-10倍 |
| CAD/3Dモデリング | AutoCAD Web、SketchUp | ネイティブ水準(すいじゅん) |
| 科学(かがく)計算 | シミュレーション、データ分析(ぶんせき) | JS比10-100倍 |
3. WASI 0.2:システムインターフェース
WASI(WebAssembly System Interface)は、Wasmがブラウザ外(がい)でファイルシステム、ネットワークなどのシステムリソースに安全にアクセスするための標準(ひょうじゅん)である。
3.1 WASI 0.2インターフェース
WASI 0.2構造:
+----------------------------------+
| wasi:cli (CLIアプリサポート) |
| wasi:http (HTTPクライアント/サーバー) |
| wasi:filesystem (ファイルシステムアクセス) |
| wasi:sockets (ネットワークソケット) |
| wasi:clocks (時間関連) |
| wasi:random (乱数生成) |
| wasi:io (ストリームI/O) |
+----------------------------------+
| Component Model (基盤レイヤー) |
+----------------------------------+
| Wasm Core (実行エンジン) |
+----------------------------------+
3.2 WASI HTTPサーバー(Rust)
// Rust + WASI HTTPサーバー
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct TodoItem {
id: u32,
title: String,
completed: bool,
}
#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
let method = req.method().as_str();
let path = req.path();
match (method, path) {
("GET", "/api/todos") => {
let todos = vec![
TodoItem { id: 1, title: "Learn WASI".into(), completed: false },
TodoItem { id: 2, title: "Build Wasm app".into(), completed: false },
];
Ok(Response::builder()
.status(200)
.header("content-type", "application/json")
.body(serde_json::to_string(&todos)?)
.build())
},
("POST", "/api/todos") => {
let body: TodoItem = serde_json::from_slice(req.body())?;
Ok(Response::builder()
.status(201)
.header("content-type", "application/json")
.body(serde_json::to_string(&body)?)
.build())
},
_ => Ok(Response::builder()
.status(404)
.body("Not Found")
.build())
}
}
3.3 Capability-Basedセキュリティモデル
WASIはCapability-Based Securityを中核(ちゅうかく)とする。プログラムは明示的(めいじてき)に付与(ふよ)された権限(けんげん)のみ使用(しよう)できる。
# WASI実行時の権限付与例
# 特定ディレクトリのみ読み取り許可
wasmtime run --dir /data::/data:readonly my-app.wasm
# ネットワークアクセス許可
wasmtime run --tcplisten 0.0.0.0:8080 my-server.wasm
# 環境変数の渡し
wasmtime run --env KEY=VALUE my-app.wasm
従来のセキュリティモデル(Ambient Authority):
プロセス -> [全ファイルシステムアクセス可能]
-> [全ネットワークアクセス可能]
-> [全環境変数読み取り可能]
WASIセキュリティモデル(Capability-Based):
Wasmモジュール -> [/dataディレクトリのみ読み取り可能]
-> [localhost:8080のみリスン可能]
-> [指定された環境変数のみアクセス可能]
4. Component Model:モジュール合成(ごうせい)
Component Modelは、Wasmモジュールを組(く)み合(あ)わせて複雑(ふくざつ)なアプリケーションを構成(こうせい)する標準(ひょうじゅん)である。
4.1 WIT(Wasm Interface Type)
// todo.wit - インターフェース定義
package example:todo@0.1.0;
interface types {
record todo-item {
id: u32,
title: string,
completed: bool,
}
variant todo-error {
not-found(string),
validation-error(string),
storage-error(string),
}
}
interface todo-store {
use types.{todo-item, todo-error};
list-todos: func() -> result<list<todo-item>, todo-error>;
get-todo: func(id: u32) -> result<todo-item, todo-error>;
create-todo: func(title: string) -> result<todo-item, todo-error>;
update-todo: func(id: u32, title: string, completed: bool) -> result<todo-item, todo-error>;
delete-todo: func(id: u32) -> result<_, todo-error>;
}
world todo-app {
import wasi:http/outgoing-handler@0.2.0;
import wasi:logging/logging;
export todo-store;
}
4.2 コンポーネント合成
# 複数コンポーネントを組み合わせて一つのアプリを構成
# 1. 各コンポーネントをビルド
cargo component build --release # Rustコンポーネント
componentize-py -d todo.wit -w todo-app app.py # Pythonコンポーネント
# 2. コンポーネント合成
wasm-tools compose \
--definitions auth-component.wasm \
--definitions db-component.wasm \
app-component.wasm \
-o composed-app.wasm
# 3. 合成されたコンポーネントを実行
wasmtime serve composed-app.wasm
4.3 Component Modelの利点(りてん)
| 利点 | 説明 |
|---|---|
| 言語独立的合成 | Rust + Python + Goモジュールを一つに |
| 型安全なインターフェース | WITで定義された契約(けいやく)を保証(ほしょう) |
| サンドボックス隔離 | コンポーネント間メモリ隔離 |
| 軽量(けいりょう) | コンテナ比数十倍軽い |
| 高速起動 | マイクロ秒レベルの初期化 |
| 移植性 | どこでも実行可能 |
5. サーバーサイドWasmフレームワーク
5.1 Fermyon Spin
SpinはWasmベースのマイクロサービスを構築(こうちく)するためのフレームワークである。
# spin.toml - Spinアプリ設定
spin_manifest_version = 2
[application]
name = "my-api"
version = "1.0.0"
description = "WasmベースAPIサーバー"
[[trigger.http]]
route = "/api/hello"
component = "hello"
[[trigger.http]]
route = "/api/users/..."
component = "users"
[component.hello]
source = "target/wasm32-wasi/release/hello.wasm"
allowed_outbound_hosts = []
[component.users]
source = "target/wasm32-wasi/release/users.wasm"
allowed_outbound_hosts = ["https://api.example.com"]
key_value_stores = ["default"]
sqlite_databases = ["default"]
// Spin HTTPハンドラー(Rust)
use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
use spin_sdk::key_value::Store;
#[http_component]
fn handle_request(req: Request) -> anyhow::Result<impl IntoResponse> {
// Key-Valueストア使用
let store = Store::open_default()?;
match req.method().as_str() {
"GET" => {
let key = req.path().trim_start_matches("/api/users/");
match store.get(key)? {
Some(value) => Ok(Response::builder()
.status(200)
.header("content-type", "application/json")
.body(value)
.build()),
None => Ok(Response::builder()
.status(404)
.body("Not found")
.build()),
}
},
"POST" => {
let body = req.body().to_vec();
let key = format!("user:{}", uuid::Uuid::new_v4());
store.set(&key, &body)?;
Ok(Response::builder()
.status(201)
.header("content-type", "application/json")
.body(body)
.build())
},
_ => Ok(Response::builder()
.status(405)
.body("Method not allowed")
.build()),
}
}
# Spinアプリのビルドと実行
spin build
spin up # ローカル実行(ポート3000)
# Fermyon Cloudにデプロイ
spin deploy
5.2 wasmCloud
wasmCloudは分散(ぶんさん)Wasmアプリケーションプラットフォームである。
# wadm.yaml - wasmCloudアプリマニフェスト
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: my-api
annotations:
description: "wasmCloud HTTP API"
spec:
components:
- name: api-handler
type: component
properties:
image: ghcr.io/myorg/api-handler:0.1.0
traits:
- type: spreadscaler
properties:
instances: 5
- type: link
properties:
target: httpserver
namespace: wasi
package: http
interfaces: [incoming-handler]
- name: httpserver
type: capability
properties:
image: ghcr.io/wasmcloud/http-server:0.22.0
traits:
- type: link
properties:
target: api-handler
namespace: wasi
package: http
interfaces: [incoming-handler]
source_config:
- name: default-http
properties:
address: 0.0.0.0:8080
5.3 サーバーサイドWasmフレームワーク比較(ひかく)
| 特性 | Fermyon Spin | wasmCloud | Lunatic |
|---|---|---|---|
| 焦点(しょうてん) | HTTPマイクロサービス | 分散アプリケーション | アクターモデル |
| デプロイモデル | 単一ノード/クラウド | 分散格子(lattice) | クラスター |
| ストレージ | KV、SQLite、Redis | Capability Provider | 内蔵(ないぞう) |
| 言語サポート | Rust、Go、JS、Python | Rust、Go、AssemblyScript | Rust、AssemblyScript |
| コールドスタート | 1ms未満 | 1ms未満 | 数ms |
| 成熟度(せいじゅくど) | GA | GA | 初期(しょき) |
| クラウドサービス | Fermyon Cloud | Cosmonic | なし |
6. Docker + Wasm
Docker DesktopはWasmコンテナをネイティブにサポートする。
6.1 Docker Wasmアーキテクチャ
従来のLinuxコンテナ:
Docker Engine -> containerd -> runc -> Linuxコンテナ
(フルOS、数十〜数百MB)
Wasmコンテナ:
Docker Engine -> containerd -> runwasi -> Wasmランタイム(wasmtime/wasmedge)
(Wasmモジュール、数MB)
6.2 Wasm Dockerイメージビルド
# Dockerfile.wasm - Wasmコンテナイメージ
FROM scratch
COPY target/wasm32-wasi/release/my-app.wasm /my-app.wasm
ENTRYPOINT ["/my-app.wasm"]
# Wasmイメージのビルドと実行
docker buildx build --platform wasi/wasm -t my-wasm-app .
docker run --runtime=io.containerd.wasmtime.v1 \
--platform wasi/wasm \
-p 8080:8080 \
my-wasm-app
6.3 Docker Compose with Wasm
# docker-compose.yml - Wasm + Linuxコンテナ混在
version: "3"
services:
# Wasmサービス(超軽量)
api:
image: my-wasm-api:latest
runtime: io.containerd.wasmtime.v1
platform: wasi/wasm
ports:
- "8080:8080"
environment:
- DB_HOST=postgres
# 従来のLinuxコンテナ
postgres:
image: postgres:16
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
volumes:
- pgdata:/var/lib/postgresql/data
# Wasmワーカーサービス
worker:
image: my-wasm-worker:latest
runtime: io.containerd.wasmtime.v1
platform: wasi/wasm
environment:
- QUEUE_URL=redis://redis:6379
redis:
image: redis:7-alpine
volumes:
pgdata:
6.4 Wasm vs Linuxコンテナ比較
| 特性 | Linuxコンテナ | Wasmコンテナ |
|---|---|---|
| イメージサイズ | 50MB-1GB | 1-10MB |
| 起動時間 | 100ms-数秒 | 1ms未満 |
| メモリ使用量 | 50MB-数GB | 1-50MB |
| セキュリティモデル | Namespace/cgroup | サンドボックス/Capability |
| 移植性 | Linuxカーネル必要 | アーキテクチャ非依存 |
| プロセス隔離 | OS水準 | 言語水準 |
7. Edge Wasm
7.1 Cloudflare Workers
// Cloudflare Worker(Wasmベース)
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === '/api/compute') {
// Wasmモジュールで重い計算を実行
const wasmModule = await import('./compute.wasm');
const result = wasmModule.heavy_computation(42);
return new Response(JSON.stringify({ result }), {
headers: { 'Content-Type': 'application/json' }
});
}
// KVストア使用
if (url.pathname.startsWith('/api/cache/')) {
const key = url.pathname.split('/').pop();
if (request.method === 'GET') {
const value = await env.MY_KV.get(key);
return new Response(value || 'Not found', {
status: value ? 200 : 404
});
}
if (request.method === 'PUT') {
const body = await request.text();
await env.MY_KV.put(key, body, { expirationTtl: 3600 });
return new Response('OK');
}
}
return new Response('Not found', { status: 404 });
}
};
7.2 Fastly Compute
// Fastly Compute(Rust + Wasm)
use fastly::{Error, Request, Response};
use fastly::http::StatusCode;
#[fastly::main]
fn main(req: Request) -> Result<Response, Error> {
let path = req.get_path().to_string();
match path.as_str() {
"/api/hello" => {
Ok(Response::from_status(StatusCode::OK)
.with_body_text_plain("Hello from Fastly Compute!"))
},
path if path.starts_with("/api/proxy/") => {
let backend_path = path.trim_start_matches("/api/proxy");
let mut backend_req = req;
backend_req.set_path(backend_path);
backend_req.send("origin_backend")
},
_ => {
Ok(Response::from_status(StatusCode::NOT_FOUND)
.with_body_text_plain("Not found"))
}
}
}
7.3 Edge Wasmプラットフォーム比較
| プラットフォーム | ランタイム | 言語 | コールドスタート | 無料枠 |
|---|---|---|---|---|
| Cloudflare Workers | V8 + Wasm | JS、Rust、C++ | 0ms(常時ロード) | 10万リクエスト/日 |
| Fastly Compute | Wasmtime | Rust、Go、JS | 数ms | なし |
| Vercel Edge Functions | V8 + Wasm | JS、TS | 0ms(常時ロード) | 100万実行/月 |
| Deno Deploy | V8 + Wasm | JS、TS、Wasm | 0ms | 10万リクエスト/日 |
| Fermyon Cloud | Spin | Rust、Go、JS、Python | 1ms未満 | 無料ベータ |
8. 言語別Wasmサポート
8.1 Rust - 第一級市民
RustはWasmの最(もっと)も強力(きょうりょく)な言語サポートを提供する。
// Cargo.toml
[package]
name = "my-wasm-app"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wit-bindgen = "0.25"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# ビルドターゲット
rustup target add wasm32-wasi # WASIターゲット
rustup target add wasm32-unknown-unknown # ブラウザターゲット
# ビルド
cargo build --target wasm32-wasi --release
# Componentに変換
wasm-tools component new target/wasm32-wasi/release/my_app.wasm \
-o my_app.component.wasm
8.2 Go - TinyGo
// main.go - TinyGo Wasm
package main
import (
"encoding/json"
"net/http"
spinhttp "github.com/fermyon/spin/sdk/go/v2/http"
)
type Response struct {
Message string `json:"message"`
Count int `json:"count"`
}
func init() {
spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) {
resp := Response{
Message: "Hello from Go Wasm!",
Count: 42,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(resp)
})
}
func main() {}
# TinyGoでWasmビルド
tinygo build -target=wasi -o main.wasm main.go
8.3 Python - componentize-py
# app.py - Python Wasm (Spin)
from spin_sdk.http import IncomingHandler, Request, Response
import json
class IncomingHandler(IncomingHandler):
def handle_request(self, request: Request) -> Response:
if request.method == "GET" and request.uri == "/api/hello":
body = json.dumps({
"message": "Hello from Python Wasm!",
"path": request.uri,
})
return Response(
200,
{"content-type": "application/json"},
bytes(body, "utf-8")
)
return Response(404, {}, b"Not found")
8.4 言語サポート比較
| 言語 | Wasm成熟度 | WASIサポート | Component Model | バイナリサイズ | 備考(びこう) |
|---|---|---|---|---|---|
| Rust | 非常に高い | 完全 | 完全 | 1-5MB | 第一級市民 |
| C/C++ | 高い | 完全 | 部分的 | 0.5-3MB | Emscripten |
| Go(TinyGo) | 中程度 | 完全 | 完全 | 2-10MB | 標準Go一部未対応 |
| Python | 中程度 | 完全 | 完全 | 10-30MB | componentize-py |
| JavaScript | 中程度 | 完全 | 完全 | 5-15MB | jco |
| C#(.NET) | 中程度 | 部分的 | 初期 | 10-50MB | NativeAOT-LLVM |
| Swift | 初期 | 部分的 | 初期 | 5-20MB | SwiftWasm |
| Kotlin | 初期 | 部分的 | 初期 | 10-30MB | Kotlin/Wasm |
9. パフォーマンス比較
9.1 コールドスタート比較
| プラットフォーム | コールドスタート | メモリ使用量 | 備考 |
|---|---|---|---|
| Wasm(Spin) | 0.5-1ms | 2-10MB | マイクロ秒水準 |
| Wasm(wasmtime) | 1-5ms | 5-20MB | 汎用的 |
| Lambda(Python) | 150-300ms | 50-128MB | VPC追加でさらに遅い |
| Lambda(Java) | 800-3000ms | 128-512MB | SnapStartで改善可能 |
| Dockerコンテナ | 500-5000ms | 50MB-1GB | イメージサイズ依存 |
| Cloud Run | 300-2000ms | 128MB-8GB | インスタンスタイプ依存 |
9.2 スループット比較
HTTP "Hello World" ベンチマーク(単一インスタンス):
Spin(Rust/Wasm): ~150,000 req/s
Native Rust(Actix): ~200,000 req/s
Go(net/http): ~120,000 req/s
Node.js(Express): ~30,000 req/s
Python(FastAPI): ~10,000 req/s
Wasmはネイティブの70-90%のパフォーマンスを達成
9.3 メモリ効率(こうりつ)
単一HTTPサービスのメモリ使用量:
Wasm(Spin): 2-5 MB
Wasm(wasmtime): 5-15 MB
Node.js: 30-80 MB
Python: 30-60 MB
Java(JVM): 100-300 MB
.NET: 50-150 MB
Go: 10-30 MB
1GBメモリでの同時サービス数:
Wasm:約200サービス
Node.js:約15サービス
Java:約5サービス
10. セキュリティモデル
10.1 Wasmサンドボックス
従来のプロセス:
+------------------------------------------+
| プロセス |
| - 全ファイルシステムアクセス |
| - 全ネットワークアクセス |
| - 無制限システムコール |
| - 他プロセスメモリアクセス(exploit時) |
+------------------------------------------+
Wasmサンドボックス:
+------------------------------------------+
| Wasmモジュール |
| +------------------------------------+ |
| | 線形メモリ(モジュール専用) | |
| | - 境界検査(bounds checking) | |
| | - ホストメモリアクセス不可 | |
| +------------------------------------+ |
| | 許可されたシステムインターフェースのみ | |
| | - wasi:filesystem(指定パスのみ) | |
| | - wasi:sockets(指定アドレスのみ) | |
| +------------------------------------+ |
+------------------------------------------+
10.2 Capability-Based Security原則(げんそく)
| 原則 | 説明 | 例 |
|---|---|---|
| No Ambient Authority | デフォルト権限なし | ファイルシステム/ネットワークアクセス不可 |
| 最小権限の原則 | 最低限の権限のみ付与 | 特定ディレクトリのみアクセス許可 |
| 明示的Capability渡し | 明示的な権限伝達 | ホストがハンドルを渡す |
| 取り消し可能 | 権限回収(かいしゅう)可能 | ランタイムで権限除去 |
10.3 セキュリティ比較
| セキュリティ側面 | コンテナ | Wasm |
|---|---|---|
| 隔離レベル | OS水準(cgroup/namespace) | 言語水準(バイトコード検証) |
| メモリ安全 | カーネルに依存 | 境界検査内蔵 |
| システムコール | seccompでフィルタリング | WASIで制限 |
| 脱出可能性 | カーネル脆弱性で可能 | 非常に困難 |
| 権限モデル | ユーザー/グループベース | Capabilityベース |
| コード検証 | なし | ロード時検証 |
11. 実践(じっせん)ユースケース
11.1 プラグインシステム
// ホストアプリケーション - プラグインローダー
use wasmtime::*;
use wasmtime_wasi::WasiCtxBuilder;
fn load_plugin(plugin_path: &str) -> Result<(), Box<dyn std::error::Error>> {
let engine = Engine::default();
let mut linker = Linker::new(&engine);
wasmtime_wasi::add_to_linker(&mut linker, |s| s)?;
// プラグインに最小権限のみ付与
let wasi = WasiCtxBuilder::new()
.inherit_stdout() // stdoutのみ許可
// ファイルシステムアクセスなし
// ネットワークアクセスなし
.build();
let mut store = Store::new(&engine, wasi);
let module = Module::from_file(&engine, plugin_path)?;
let instance = linker.instantiate(&mut store, &module)?;
// プラグイン関数呼び出し
let process = instance
.get_typed_func::<(i32,), i32>(&mut store, "process")?;
let result = process.call(&mut store, (42,))?;
println!("Plugin result: {}", result);
Ok(())
}
11.2 エッジコンピューティング
Edge Wasmアーキテクチャ:
ユーザーリクエスト -> [CDN Edge(300+ PoP)]
|
v
[Wasm Worker]
|
+-> キャッシュヒット:即座に応答(0ms)
|
+-> キャッシュミス:オリジンサーバーにリクエスト
| |
| v
| [Origin Server]
| |
v v
[応答 + キャッシュ保存]
利点:
- ユーザーに最も近い場所で実行
- コールドスタートほぼなし
- グローバル分散自動デプロイ
11.3 ブロックチェーンスマートコントラクト
複数(ふくすう)のブロックチェーンがWasmをスマートコントラクト実行エンジンとして採用(さいよう)している。
| ブロックチェーン | Wasmランタイム | 言語サポート |
|---|---|---|
| Polkadot | Substrate | Rust(ink!) |
| Near | Wasmer | Rust、AssemblyScript |
| Cosmos(CosmWasm) | Wasmer | Rust |
| Dfinity(ICP) | カスタム | Rust、Motoko |
12. Wasm vs Container比較
12.1 総合(そうごう)比較
| 特性 | Wasm | コンテナ |
|---|---|---|
| 起動時間 | マイクロ秒-ミリ秒 | ミリ秒-秒 |
| イメージサイズ | 1-50MB | 50MB-数GB |
| メモリ使用量 | 1-50MB | 50MB-数GB |
| CPUオーバーヘッド | 0-30% | 0-5% |
| セキュリティ | 強いサンドボックス | OS水準隔離 |
| ネットワーキング | WASI(制限的) | 完全サポート |
| ファイルシステム | WASI(制限的) | 完全サポート |
| GPUサポート | 実験的 | 完全サポート |
| エコシステム | 成長中 | 非常に成熟 |
| 状態管理 | Stateless推奨 | Stateful可能 |
12.2 いつWasmを選択するか
Wasm選択基準:
- ミリ秒以下のコールドスタートが必要
- 極限(きょくげん)の軽量サービス
- プラグイン/拡張システム
- エッジコンピューティング
- 多言語モジュール合成
- 強いサンドボックス隔離が必要
- リソース制約環境(IoT)
コンテナ選択基準:
- 複雑なネットワーキング
- GPU使用
- レガシーアプリケーション
- 豊富(ほうふ)なエコシステムが必要
- 状態保存が必要
- 大容量メモリ/ストレージ
13. 将来(しょうらい)展望(てんぼう)
13.1 進行中のWasm提案
| 提案 | ステータス | 説明 |
|---|---|---|
| GC(Garbage Collection) | Phase 4 | Java、Kotlin、DartなどGC言語サポート |
| Threads | Phase 3 | 共有メモリマルチスレッディング |
| SIMD | Phase 4(完了) | 128ビットSIMD演算 |
| Exception Handling | Phase 4 | try/catchネイティブサポート |
| Stack Switching | Phase 2 | コルーチン、async/awaitサポート |
| Memory64 | Phase 3 | 64ビットメモリアドレス |
| Branch Hinting | Phase 3 | 分岐予測ヒント |
| Tail Call | Phase 4(完了) | 末尾(まつび)呼び出し最適化 |
13.2 Wasm将来ロードマップ
2025-2026展望:
- WASI 0.2完全安定化・主要クラウド採用
- Component Modelエコシステム成熟
- Docker Wasmプロダクションレディ
- GC proposal主要ランタイム実装
- Threads proposal安定化
2027+展望:
- Wasmがコンテナと同等の地位
- Edge-firstアーキテクチャのデフォルトランタイム
- IoT/組み込みの標準実行環境
- 多言語コンポーネントエコシステム確立
14. クイズ
Q1. WASIの中核セキュリティモデルは何か?
正解:Capability-Based Security(権限ベースセキュリティ)
WASIは「No Ambient Authority」原則に従う。Wasmモジュールはデフォルトで何の権限もなく、ホストが明示的に付与したcapability(ファイルハンドル、ネットワークソケットなど)のみ使用できる。従来のUnixのambient authorityモデルとは対照的である。
Q2. Wasm Component Modelの利点は?
正解:
- 言語独立的合成:Rust、Python、Goなど異なる言語で書かれたモジュールを一つに組み合わせ可能
- WITインターフェース:型安全な契約でモジュール間通信
- サンドボックス隔離:各コンポーネントは自身のメモリ空間を持つ
- 軽量:コンテナ比数十倍軽い
Q3. WasmのコールドスタートがLambdaより速い理由は?
正解:
- Wasmバイナリは1-10MBと非常に小さくローディングが速い
- ランタイム初期化がマイクロ秒水準(JVMやPythonインタプリタのような重い初期化なし)
- AOTコンパイルされたバイナリを直接実行
- 線形メモリモデルでシンプルなメモリ設定
- プロセス/コンテナ作成オーバーヘッドなし
Q4. Docker + Wasmはどう動作するか?
正解:
Docker Desktopはcontainerdのrunwasi shimを使用してWasmコンテナを実行する。従来のruncの代わりにwasmtimeやwasmedgeなどのWasmランタイムがコンテナを実行する。FROM scratchベースのイメージに.wasmファイルのみを含めて超軽量イメージを作成でき、docker-composeでLinuxコンテナとWasmコンテナを混在運用できる。
Q5. Wasmがまだコンテナを置き換えられない理由は?
正解:
- WASIのシステムインターフェースがまだ制限的(GPU、複雑なネットワーキングなど)
- エコシステムがコンテナに比べて未成熟
- レガシーアプリケーションの移行が困難
- 状態管理が基本的にstateless
- デバッグツールがまだ発展途上
- 一部言語のWasmサポートが初期段階
ただし、Wasmはコンテナを「置き換える」のではなく「補完する」技術であり、エッジと軽量サービス領域でコンテナと共存する見通しである。
15. 参考資料(さんこうしりょう)
- WebAssembly公式サイト - https://webassembly.org/
- WASI公式ドキュメント - https://wasi.dev/
- Component Model仕様 - https://component-model.bytecodealliance.org/
- Fermyon Spinドキュメント - https://developer.fermyon.com/spin/
- wasmCloudドキュメント - https://wasmcloud.com/docs/
- Bytecode Alliance - https://bytecodealliance.org/
- wasmtimeランタイム - https://wasmtime.dev/
- Docker Wasmガイド - https://docs.docker.com/desktop/wasm/
- Cloudflare Workers - https://developers.cloudflare.com/workers/
- Fastly Compute - https://developer.fastly.com/learning/compute/
- wasm-tools - https://github.com/bytecodealliance/wasm-tools
- WIT仕様 - https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md
- componentize-py - https://github.com/bytecodealliance/componentize-py