2006年10月21日の日記

<2006/10/22 2006/10/20>

auto_resource実装案

Bomber丸Worldのリソース管理システム(auto_resource)のメモリ管理を考えていました。
メモリ確保のほうはshared_resourceと同じで全く問題ないのですが、メモリ解放が問題なのです。
メモリ確保をしていくうちにメモリが足りなくなったら最近使われていないものからメモリを解放していくのですが、その実装方法がいくつかあって、どれを選ぶべきかというのが難しかったのです。

考えている方法は三つあって、一つ目はその時点で使われていなければ新しかろうと古かろうと片っ端から全て解放してしまうというものです。
解放の際には全てのリソースが入っているコンテナの中身を全て走査して参照カウントが0のものを全て解放します。
この方法は最も実装が簡単で消費メモリも少なくなりますが、一時的に使わなくなったりソースを後のために取っておくというauto_resourceの考え方に反してついさっきまで使っていてまたすぐ使うかもしれないものまでどんどん解放していってしまいます。
マップ切り替えなどで一度に大量のリソースを読み込んで解放する場面ではすごくまずいことになります。

二つ目の方法は、字面通り最後に使われた時間が一番古いものから順番に解放してゆく方法です。
これを現実的な処理時間で実現しようと思えば、リソース参照用のファイル名-リソースを関連付けたマップのほかに、今まで使った順番に並べられたリストが必要になり、必然的にリソース本体とは別の余計なメモリが必要になります。
更にリソース側にも、解放や順番の並び替えの高速化のためにリストやマップへのイテレータが必要になります。
リストの実装によっては更に難しいコーディングが必要になるかもしれません。
そして当然、使用するたびに使用時刻の更新やリストの並び替えが発生するのでパフォーマンスは低下します。
ファイル読み込みによるパフォーマンス低下を嫌ってauto_resouceを作ろうとしたのに全く逆効果の可能性すらあるのです。
解放の際にはリストの末尾から順番に見て行って規定のメモリ以内に収まるか全て走査し終えるまで参照カウントが0のものを解放していきます。

三つ目の方法は、上記二つの中間を取って、ある時間より古ければ数が多かろうと少なかろうと全部解放してしまうという方法です。
これであれば、一つ目の方法ほど無駄は出ませんし、順番を考える必要が無いので二つ目の方法のようにリストを保持しておく必要がありません。
解放の際には適当にしきい時刻を決め、全てのリソースが入っているコンテナの中身を全て走査して参照カウントが0かつ使用時刻がしきい時刻より古い場合には解放します。
これの問題点は、しきい時刻の決め方やリソースの使用状況によって著しく性能が変化するということです。

それぞれ長所と短所がありますが、まず一つ目の方法は通常時には問題外ですが終了時に全てのリソースを解放する必要があるときには効果を発揮します。
二つ目はリソース自体の消費メモリが大きかったり使用するときの実行時間が長いなど、欠点が問題にならないほどスケールの大きいものであれば相対的に長所のみが残って最善の手段となります。
三つ目は二つの中間的なものなので無難としかいえません。
そんなこんなで、三つとも実装してみる価値はありそうです。

GChatの管理画面の改良を行いました。
まず、辞書画面での検索機能です。
これにより辞書への重複登録ということは少なくなったはずです。
そして、なぜか今までずっと実装していなかった全ログ確認機能。
これでもう直接ログファイルを見る必要はなくなったのです。
そんなこんなでアルニックもレベル29になりました。

<2006/10/22 2006/10/20>