Rubyの実行時間を計ってみる
項番 | 処理 | 時間 | カラループを引いた実時間 |
---|---|---|---|
1 | カラループ | 0.34 | 0 |
2 | a=0 | 0.65 | 0.31 |
3 | a=1+1 | 1.07 | 0.73 |
4 | a=1*1 | 1.09 | 0.75 |
5 | a=d | 0.65 | 0.31 |
6 | a=d*2 | 1.1 | 0.76 |
7 | a=d+d | 1.08 | 0.74 |
8 | a=0.1+0.1 | 1.36 | 1.02 |
9 | a=0.1*0.1 | 1.35 | 1.01 |
10 | a=map[2][2] | 1.41 | 1.07 |
11 | a=map[2*2+2] | 1.93 | 1.59 |
Celeron1.8GHzのPCを使っている。
HPCモジュールを使って、1000回実行した時間を計ってみた。単位はミリ秒。
誤差が大きいからさらに1000回ループして、1000で割った値だ。
3回実行して少ない値を取った。
計算については、基本的にはメソッド呼び出し数に依存している。
掛け算より足し算のほうが若干速いが、d*2をd+dに書き換えるほどの差でもない。
労力をかけるだけ無駄だ。
整数より実数のほうが遅い。
必要がない限りは整数にしたほうがいいだろうが、アルゴリズムを細工してまで整数にこだわるほどの差ではない。
10番のmapは2次元配列で、11番はそれを1次元配列にしたものだ。
2次元配列が遅く、それを1次元配列に平坦化したら速くならないかと思ったのだが、計算のメソッドが増えたせいで逆に遅くなった。
DXRubyExtensionで高速マップデータアクセス手段を提供する必要性は微妙なところだ。
でも、たとえば2次元配列は右や下にはみだした場合の処理が面倒で、それ用のクラスで「ループさせる」「範囲外は指定のデータに固定する」などを提供できれば、楽になるし速くなるということで需要はなきにしもあらず。
でもやっぱり微妙だ。
ループも試してみた。
項番 | 処理 | 時間 | カラループを引いた実時間 |
---|---|---|---|
1 | for i in 0..9 do end | 6.59 | 6.25 |
2 | 10.times do end | 4.65 | 4.31 |
3 | (0..9).each do end | 5.59 | 5.25 |
4 | 0.upto(9) do end | 4.77 | 4.43 |
2番と4番、イテレータブロックで値を受け取ると、1番とほぼ同じ時間になる。
はてな記法のテーブルで|をエスケープする方法がわからなかったので書いてないだけだ。
それぞれ10回ループした時間だから、1回の時間はかなり少ないことがわかる。
3番が一番遅いが、こんな書き方わざわざしないだろう。
マップチップをたくさん描画する場合に、こうしたら速い、みたいなやりかたが無いかと思ったのだが、特にそういったものは無いようだ。
そして、これを見る限りDXRubyExtensionという形で何かを提供してみても、根本的解決にはならないことが想像できる。
やはりRPGのようなゲームの描画周りで凝ったことをしようと思うと、現状のDXRubyでは厳しいのだ。
また、Rubyの特徴は実にわかりやすく「全般的に遅い」ということになる。
言い換えれば、ループによる大量処理といった負荷が集中する場合に弱い。
Rubyゲームプログラミングを改善していこうと思ったら、そういう部分にフォーカスしてくのがよさそうだ。
たとえば背景描画も、ループと描画登録をCの中だけで完結させれば、相当なパフォーマンス改善になるはずだ。
逆に言えば、Rubyは全体としてそれなりのパフォーマンスが出るから、大量のループ以外はRubyで書いても問題にはなりにくい。
従って、Cでフレームワークを作ってRubyで処理内容を書く、というアプローチは、覚えるのが面倒になるだけでパフォーマンス的には意味が無い。
DXRubyのスタンスは、基本的にはゲームのアルゴリズムはすべてRubyで書く。
だが、最低限のことすら遅すぎて無理な場合、そもそもそれはRubyでは作れないということになってしまい、そこがRubyゲームプログラミングの限界になる。
そういった部分を解決していけたらいいと思う。