Javascriptベンチを作ってみた(Canvasもの)

# はじめに

ゲームものにはベンチマークがついているものです。[FF XIV 紅蓮の解放](http://jp.finalfantasyxiv.com/benchmark/)だってリリース前にベンチマークが公開されたりしています。ベンチマークの結果から、どこまで自分のPCが快適にできるのか、もしくはどこまで投資(CPU/GPUなど)すべき(しないといけないの)か判断できるためです。まぁ、一部のユーザ(私もその中に入りますが)にはベンチマークが目的になることもありますが。

一昔前はブラウザのJavascriptやHTMLのレンダーのベンチマークがたくさんあったような気がします。けどGoogleが作成した[Octane](https://developers.google.com/octane/?hl=ja)がリタイアしたり、[Peacekeeper](http://peacekeeper.futuremark.com/)もずっと前からやめたり、[JetStream](http://browserbench.org/JetStream/)や[Kraken](https://krakenbenchmark.mozilla.org/)も更新されなかったりと残念なところです。知りませんでしたが[oortpnlie](http://oortonline.gl/)とかもあるのですね。

まぁ、ブラウザ用のゲームを作るならばWebAssembly対応するのがトレンドでしょうか。

けど、そうはいっても、WebAssemblyもWebGLも敷居が高そうなのでCanvas対応のベンチマーク程度ならば簡単に作れなくもないなと思い作ってみました。

ついでに、作成したのは前に公開した"[Cordovaで作成したアプリをElectronを用いてWindowsアプリ化してみる（手順と移植の問題点）](http://qiita.com/rakichiki/items/45fca916e2778e31c568)"のをベンチマーク対応したものです（実は機能的にほぼほぼ入っていて、他ブラウザでも動作させるように修正した程度でした）。

# ベンチマークを作成するにあたり

Canvasでアニメーションを行うには定期的に描画を行うのが普通です。昔ならばsetTimeout/setIntervalを使うのが主流だったと思います。

```
animation_timer_id = setTimeout(func, timeout);
```

ただ、これだとうまくいかないケースや非表示タブでもフルで動いてしまうため、非表示タブでは動作を低くしたり、60fpsをめどに呼び出す関数がサポートされたのがrequestAnimationFrameです。

```
animation_timer_id = requestAnimationFrame(func);
```

ただ、requestAnimationFrameは、60fpsを目標に動くため、そこまで速くなくてもいいやというケースには使いづらくなります。遅くてもいいよとなると以下のようにしないといけません。

```
var now_date = new Date();
if (now_date.getTime() - before_time < timeout) {
	animation_timer_id = requestAnimationFrame(func);
        return;
}

～描画機能～

before_time = now_date.getTime();
animation_timer_id = requestAnimationFrame(func);
```


before_time(どこかに保存しておかないといけませんが)に前回描画した時間を登録しておき、次に起こされたら時間を比較し、もしまだ描画時間に到達していなければもう一度requestAnimationFrameで寝る処理を入れないといけません。

requestAnimationFrameは60fpsをぎりぎり目指すにはいい関数ですが、30fpsでもいいんやとなるとオーバーヘッドがちょっと増えるのが気になります。

ついでに、GaiHexは通常のゲームの描画にはrequestAnimationFrameを使用し速度を調整していますが、setTimeoutでも結構いけるんじゃない？と思いベンチマークにはsetTimeoutを採用してみました。

# ベンチマーク実行と結果

前回作成した([GaiHex](http://qiita.com/rakichiki/items/45fca916e2778e31c568))にものにベンチマークを入れてみました。また、ElectronはChromiumがベースですが、IE(Edge)/Firefox/Operaでもうまく動くようにしました(前から動くことは動いていたのですが、少し問題があり)。また、ベースがAndroid対応だったのでAndroid(Nexus 9 Android 7.1.1)で動かしています。また、手元にあるiPhone 6s Plus(iOS 10.3.1)でも動かしてみました。

動かし方はIE/Android/iPhone 6s Plus以外は、[前回](http://qiita.com/rakichiki/items/45fca916e2778e31c568)説明した通りに、gitcloneしていただきindex.htmlをブラウザで読み込んでください。

けど、IE/Android/iPhone 6s Plusは少し面倒なのでURLを[公開](http://mizuao.news.coocan.jp/gaihex/)します(ベンチマークだけではなくフルに遊べれるよ)。

このページにアクセスしてはじめのページを見るとトップメニューにベンチマークのボタンが表示されます。

![benchmark1.png](https://qiita-image-store.s3.amazonaws.com/0/176294/7f6921db-3a55-dd5e-6f48-1814b8f08c1e.png)

次に、各種メニューを表示されます。ゲーム時間が60、マップはbalance、ユニット数を12、ハンデを0、上位ユニットをgame、ロストターンを1-3、レベルアップをskill、陣営は見方が白、敵を赤色をしてすると２分前後で結果が出ます(オプション的にヒットポイントのみ表示)。ターン数も61で終わります。

![benchmark3.png](https://qiita-image-store.s3.amazonaws.com/0/176294/d380a912-02c4-399f-f357-f58cb385ca37.png)


ブラウザをフルサイズで動かすThinkPad X270(Core i7-6500U 2.5GHz)とだいたい以下の結果になります。また、Nexus 9に合わせるためにブラウザに限っては画面を縦に変更して実行もしてみました。

![benchmark2.jpg](https://qiita-image-store.s3.amazonaws.com/0/176294/fb1020dc-8312-e38a-3a70-f42450dceb8c.jpeg)

まぁ、縦にするとテーブルやボタンは崩れてしまいますがご容赦ください（こんなのでゲームはできないでしょうが）。なぜ縦にしないといけないかというと、このプログラムは解像度によってサイズを変更できるようにしているのですが、縦長に合うようにしており横長にして縦の高さに依存してサイズを大きくできないのです。このため画面を縦にすることで高さを大きくすることでサイズアップが可能なのです（この辺りが解像度のパターンが多いAndroidの問題ではないかと思ったりしております）。


|		|バージョン	|サイズ	|FPS|
|:--------------|---------------|-------|---|
|Chrome 		|58.0.3029.81	|680x779	|　131.5|
|↑		|↑		|1,133x1,298	|　126.6|
|Firefox 	|53.0		|680x779	|　135,4|
|↑		|↑		|1,133x1,298	|　139.4|
|IE		|15.15063	|680x779	|　181.0|
|↑		|↑		|1,133x1,298	|　181.0|
|Opera		|44.0.2510.1449	|680x779		|　131.9|
|↑		|↑		|1,133x1,298		|　124.4|
|Electron	|56.02924.87	|680x779			|　134.5|
|Nexus 9(Chrome)		|53.0.2785.135		|1,134x1,298	|　 69.5|
|iPhone 6s Plus(Safari) 	|602.1	|1,134x1,299	|　131.3|

若干ブラウザとNexus 9/iPhone 6s Plusではサイズが違っていますが、あまり変わりないでしょう（表のくっつけるのがわからなくて上のようにしています）。

Electronだけサイズは違いますが、コンフィグなどの修正が必要なので試していません。Chromiumを使用しているので傾向はわからないかなと思います。

# 考察

結果は、スペックミスでない本当に120MHzで表示させることができるディスプレイで見ないとわからないかもしれません。ThinkPad X270やNexus/iPhoneのディスプレイの描画間隔はわかりませんが、描画できているとは思えません。

結果はあまりにも軽すぎてベンチとしてイケていなさすぎました。一応言い訳として最初はもう少し重かったのですがAndroid向けのため頑張って軽くしたら...思いのほか軽すぎるものになってしまいました。

ついでにrequestAnimationFrameを使用するとどのブラウザでも60fpsを少し切るぐらいで変わらないので、ベンチマークだけsetTimeoutを使いましたが、あまりにも高速すぎて、あれな結果になってしまいましたが。

もっと画面が広くして描画負担が重くしないと比較できない感じがしています。昨今のブラウザではWebGLがサポートしている現状を考えるとCanvasベンチはもう軽すぎるかなと思わなくもありません。

ベンチマークを作成した理由は、Cordovaを用いてWindowsアプリを作成しようとするとブラウザがIE(Edge)になるため、IE対応を先に進めた次第です。