2014年4月23日水曜日

C++: 動的なプロパティーシステムの実装比較

アクションゲームやシューティングゲームを作る場合には一般にゲームの世界の中でたくさんのゲーム内オブジェクトが動き、ゲームの世界が時間的に進行します。

今回は、質量と位置と速度を持ったゲーム内オブジェクトに、オイラー法によって微小時間における力を与えたニュートンの運動方程式を計算する単純なゲーム世界を例に、

①そのような作用を計算されるゲーム内オブジェクト群を格納するコンテナーにstd::vector, std::list, std::forward_listを用いた場合に速度的な差は考慮する程度になるのか、

②ゲーム内オブジェクトの質量、位置、速度を保持するためのプロパティーの実装がクラスメンバー変数、std::{map|unordered_map}<std::string, boost:any>、boost::property_tree::ptreeとした場合の速度的な差はいかほどになるのか、

ベンチマークを行うコードを書いてみました。先に結論を書いておきます。

結論:

① コンテナーのデータ構造によるトラバース速度は有意差を呈するか

このような例ではゲーム内オブジェクト群を格納するコンテナーはstd::vectorでもstd::listでもstd::forward_listを選択しても速度に有意差は無い。アロケーターからタスクシステムを用意する変わりにコンテナーを用いてトラバースする目的だけであれば、何れを用いても差は無く、寧ろinsert/removeが不利なstd::vectorは向かないとも言える。

② 実行時にキーを追加/削除可能なプロパティーシステムの速度的なコスト

今回の例のようなほぼすべてのオブジェクトで頻繁にread/writeされるオブジェクトのプロパティーはメンバー変数で用意した方が確実に良い。スクリプトエンジン等でプロパティーのキーを実行時に追加/削除したい場合も、すべてをものぐさにそれだけで管理するのではなく、ゲーム世界全体に見てアクセス頻度の高いプロパティーはメンバー変数を持たせたクラスを定義した上で、スクリプトによる動的なプロパティーキーも提供した方がたぶん良い。

通常、オブジェクトは今回の例よりも多くのパラメーターを取り扱いたいから、そうなるとstd::{map|unordered_map}やキーのstd::stringのハッシュコストもそれなりに増加するので、ものぐさに動的プロパティーシステムだけを提供してそれだけを使えば良いという姿勢はゲームエンジンのライブラリーとしては、せっかくのC++での実装を悲しみに包む結果になる、と思われる。

boost::property_tree::ptreeをそのまま本当に実行時のプロパティーシステムに使おうとすると、例えば、今回の例のglm::vec3のようにシリアライズできない場合にはそれに対応するコスト(シリアライズ可能にするか、今回の例のように無理やりDOM構造に落としこむか)とDOM構造の複雑化を懸念しなければならくなるし、そもそも速度的には実用レベルにならない遅さなので論外。ptreeはあくまでも外部との入出力で使いましょう。

コードと結果:

0 件のコメント:

コメントを投稿