高速化

サンプルに突っ込んだdot.rbが遅い。
うちの環境でたかだが900ほど点を動かすだけで処理落ちする。
2000のスプライトが動くはずなのだが。
テクスチャのロック・アンロックに時間がかかるとばっかり思っていたが、実験的にlock、unlockメソッドを追加しても、ほとんど変わらなかった。
これは、DirectX内部でテクスチャをメインメモリとビデオメモリの両方に持っているからではないかと思っている。
書き換えはメインメモリのほうでして、実際に描画するときに変更されていたらコピーするなり、バス経由でメインメモリを参照するなりしているのだろう。
想定している通りの動作なら、テクスチャの量が増えたり、ビデオメモリが少なかったりしても、ロック・アンロックに時間はさほどかからないはずだ。
関数呼び出しが減るぶんちょっとは速くなるから無駄ではないが、そのちょっとのためにDXRubyの使い手が気にすることが増えるなら、サポートしたくないところだ。
基本的に、ライブラリが提供するクラス・メソッドの数が多ければ多いほど、多機能で柔軟でカスタマイズが効くようになるが、多ければ多いほど、逆に使う側の敷居は高くなる。
極限まで削るのは理想だが、そのために1つのメソッドが複雑になるのは本末転倒だから、バランス感覚の問題となる。
このへんの俺の感覚はWindow.draw系メソッド群に表れている。


話がそれたが、dot.rbが遅いのは描画処理そのものではなく、ピクセル描画の色指定および、色取得のための配列生成が原因なのではないか、と考える。
サンプルでは色指定の配列は定数で持たせたから、今回の例で言えば色取得のみとなる。
1000ほどのドットを動かすだけで、1フレーム16.6msで項目数4の配列を最大2000生成することになる。
ためしにgetColorメソッドを追加して、色を配列でなくて、32bitデータで返すようにしてみたところ、2000ドットまで処理落ち無しで動くようになった。
配列の生成はかなり重いらしい。
プロファイルとれって言われそうだけど、そういうのよくわかんないし。


んで、ここで問題になるのは、32bitデータがRubyではFixnumじゃなくてBignumになってしまうところ。
A8R8G8B8形式の色を32bitで表すと、Aが128以上の場合に31bit整数のFixnumに入りきらない。
配列を作らなくても、代わりに他のオブジェクトをわざわざ生成するなら、この変更には意味がない。
テストしたgetColorメソッドはINT2FIXした時点で上位1bitが削られて-1になっていたから判定できているが、これでは色が取得できているとは言えない。
対策を考えると、色を表現するColorクラスを追加するとか、色を32bitじゃなくて、Aを削ったRGBの24bitにするか、そんな感じだ。
Colorクラスを作るのは高速化という目的にはマッチしないが、24bit化は検討する意味はありそうだ。


一つのアイデアとしては、24bitで色を取得するメソッドだけ追加して、色を設定するほうは、配列で指定すればARGB、Fixnumで指定すれば24bitのRGBとする、というような仕様だ。
それで問題はなさそうだが、なんで32bit使えないの?って使う側はシンプルに疑問に思いそうだ。
つくづくDirectXRubyの相性の悪さを思い知る。