👾

Rust & Wasmでミニシューティングゲームを作る

に公開

はじめに

前回は、TypeScriptを使って、Cnavas上で動作するミニシューティングゲームを作りました。今回も、まったく同じ動作する"Rust & Wasm"版を作りました。流行の"Rust & Wasm"を使うとどれくらい早くなるのか、まったく同じ動作をするゲームを作ることで、体験して比較することが目的です。さて、Rustで作った場合ではどうでしょうか。興味を持って頂いた方は、記事中のTypeScript版と、AssemblyScript版、そして Rust&Wasm版を試してみてください🙂。
https://zenn.dev/yurioka/articles/be7b44f579c896

ミニシューティングゲーム

ミニシューティングゲーム

お試しURL

[TypeScript版] https://myurioka.github.io/barrage/
[AssemblyScript版] https://myurioka.github.io/barragewasm/
[Rust&WebAssembly版] https://myurioka.github.io/barragerust/

操作

マウス移動: 自機左右移動
クリック/タップ(プレー中): シューティング ON⇔OFF
☆シューティングが一定期間OFFの場合、数秒間、攻撃力UP
クリック/タップ: ゲーム開始/再開

ソースコード

https://github.com/myurioka/barrage/
https://github.com/myurioka/barragewasm/
https://github.com/myurioka/barragerust/

試した結果

実際に<Rust&Wasm>版を試した感覚は、<TypeScript版>、<AssemblyScript版>と比べ、少し動作が軽い感じがします。更新処理の計測値においても、一番早いのは、<Rust&Wasm>でした😄。

1 2 3 4 5 6 7 8 9 10 平均(ms)
ASC update 3 3 2 2 2 2 2 3 2 3 2.4
draw 4 5 6 5 5 5 7 5 5 5 5.2
TSC update 5 2 5 3 2 4 2 2 2 2 3.3
draw 2 2 2 2 2 2 2 2 2 2 2.1
Rust&Wasm update 2 1 1 1 1 1 1 1 1 1 1.1
draw 5 4 4 5 3 4 4 5 5 3 4.2

考察

Rust&WebAssebmlyの方が少しサクッと動くことについて、WATに出力して処理内容の差分を確認すれば何かわかるかと思ったのですが、わかりやすい答えはみつからず、五里霧中で確認している内に・・・、Rust側のWatファイルだけに、メモリーを動的に確保・解放する、あの関数がexportされていました。

  (export "__wbindgen_free" (func 212))
  (export "__wbindgen_malloc" (func 180))

この点をネットで調べると、普通に「WebAssemblyは、"さまざまな言語からコンパイルできる共通のバイトコード形式ですが、それはあくまで「実行ターゲット」が共通であるというだけです。最終的に生成されるWebAssemblyのコードは、元の言語の特性と、その言語のコンパイラの能力に大きく依存する。」ということが紹介されていました。少しサクッと動くように感じたのは、GCがないなど、元の言語の特性の違いかもしれません。調べている中で、"JS側での利用した後,グルーコード(wasm-bindgen)が明示的に解放する..."ということは、どうやって解放しているのだろう、解放されないケースは....😑などの情報もありました。WebAssembly、いろいろ学ばないといけません。

最後に

異なる言語で、同じ動作の“ミニシューティングゲーム」を三つも作りました。思い付きで始めたコーディングも、予測と違い、ほとんど性能の差が出ない結果になりましが、作成中、言語の違いに、いろんな意味で手が止まり、楽しくコーディングができました。Rustについて述べると、特に、"トレイトとクラスは違う"ということを改めて共感!?しました😄。

Discussion