WebAssembly(Rust)の実行速度を簡単な球の物理計算で性能テストしてみました。あと以前作成したゲームループに問題があったため、処理落ちしても大丈夫なように修正、改良しました。
少し古いPC(Windows10)で30FPSを維持できる個数は、Chromeで5000個、Firefox4500個、Edge2500個でした。低価格スマホ、タブレット(android、Chrome)では1000個。
球の物理計算?
物理シミュレーションではなく、それっぽく動くだけの似非物理計算です。重力での落下、壁と床の衝突、球同士の衝突の計算を行っています。球の衝突計算が重すぎるので、事前に不要な計算を省略する最適化を行っています。
球の個数を入力して[start]ボタンを押すと計算がスタートします。その時のFPSと使用メモリが表示されます。とりあえずマウスや画面タッチでカメラが回転できます(実験中)。
実行
Rustプロジェクトとソースコードです。Windowsコマンドスクリプトでのビルドになります。
“Rust(wasm)の速度性能テスト&JavaScriptでゲームループ改” をダウンロード rust_webgl_speed_test.zip – 99 回のダウンロード – 98 KB
JavaScriptでゲームループ改
以前作成したのもが処理落ちに対応できていなかったので修正、改良しました。できるだけ他のJavaScript処理に制御が移るようにsetTimeoutを利用して処理を分散させました。
ゲームループ.js
let UpdateFPS = 30;
let UpdateStepTime = 1000/UpdateFPS;//ms
let UpdateFrameSkipMax = 8;
let AnimeFrameHdl;//requestAnimationFrame
let TimeoutHdl;//setTimeout
let UpdateLastTime = 0;//前回の更新時間
let FrameSkipCnt = 0;//フレームスキップカウンター
function start()
{
// ゲームループ開始
UpdateLastTime = performance.now();
TimeoutHdl = setTimeout(update_step);
}
function update_step() {
let now_time = performance.now();
let time = UpdateLastTime;
if(time <= now_time) {
//
// 更新処理
//
time += UpdateStepTime;
FrameSkipCnt += 1;
UpdateLastTime = time;
if(time >= now_time){ //時間更新成功
FrameSkipCnt = 0;
//画面更新に合わせて描画実行
AnimeFrameHdl = requestAnimationFrame(update_render);
//TimeoutHdl = setTimeout(update_render);//合わせない
return;
}
//まだ遅れている
//間に合わない 時間リセット
if(FrameSkipCnt >= UpdateFrameSkipMax){
FrameSkipCnt = 0;
UpdateLastTime = now_time;
AnimeFrameHdl = requestAnimationFrame(update_render);
//TimeoutHdl = setTimeout(update_render);
return;
}
//フレームスキップ継続
//連続実行せずに一旦スレッドを解放
TimeoutHdl = setTimeout(update_step,0);
return;
}
// ここに来る場合、時間に余裕がある
let wait_time = time - now_time;//次回更新までの時間
if(wait_time < 0)wait_time = 0;
if(wait_time > UpdateStepTime*1.1){
UpdateLastTime = now_time;//更新処理が進みすぎ 念のため
wait_time = 0;
}
//次回更新まで待つ
TimeoutHdl = setTimeout(update_step,wait_time);
}
function update_render() {
//
// 描画処理
//
TimeoutHdl = setTimeout(update_step,0);
}