メモリの管理


メモリの管理のお話です。

ヒープ (メモリ) / 戻る / トップページ


ヒープ (メモリ)

PC 主体の海外と、コンシューマ (家庭用ゲーム機) 主体の国内では、 その意識も扱いも大きく異なります。
 
海外では PC 主体のため、メモリ容量が比較的裕福で、細かくても必要に 応じてメモリの確保と解放を行う傾向にあります。 実際の挙動よりもコードの簡潔さ、設計の綺麗さを好む傾向と言えるでしょうか。 海外発の描画・物理演算などの有名なライブラリもこのような 扱いをするものが多いです。
 
国内はコンシューマ主体のため、常にメモリ容量との戦いになります。 コンシューマ機はゲーム機自体のコスト削減のために、 メモリ容量を小さめに取っているためです。 限られた容量を上手くやりくりするには、ヒープの断片化や容量自体の量を 常に意識しなければなりません。 マップなどの大きくて一度確保したらしばらくはメモリに常駐している ようなデータと、エフェクトなどの小さくて頻繁に確保と解放を繰り返すデータ、 デバッグ時のみに使われるデータ、それぞれを別領域に確保したり、 確保のアルゴリズムを変えるなどの工夫が通常取られます。
 
また、ゲームはリリース時には完全なデバッグがされていることが 求められるため、メモリリークなどはあってはならないことです。 あらゆる状況において、メモリリークが起こらないように、 仮に起きてしまった時にはその発見と原因追求が早急に行えるように、 ヒープ管理機能の仕組みの上で対処しておくと良いでしょう。
 
ヒープ管理機能としては、以下のような機能が実装されることがあります。
 
アラインメント
 
処理速度、キャッシュへの乗り具合、メディアへのアクセス (DMA 転送)、 CPU 自体の制限などのために、特定のアラインメントに沿ったアドレスに メモリを確保します。
 
ユーザヒープ
 
ヒープの中にさらにヒープを確保します。ヒープを用途別に分ける事で、 互いのヒープの動きに影響を受けなくなるため、安定した動作 (断片化が 起こりにくいなど) を確保できるようになります。また、確保量の大きさや 頻度に応じた最適化を行うこともできる利点もあります。
 
ハイメモリ/ローメモリ
 
ヒープからメモリを取得する際に、上位からと下位からの取得で分けられます。 小さくて頻繁に確保されるメモリと、大きくてまれにしか確保・解放されない メモリを切り分けるときなどに使われます。
 
確保時のメモリフィル
 
便利なため、また使用側が初期化し忘れても良いように、 メモリ確保時に 0 フィルを行うことがあります。
 
解放時のメモリフィル
 
メモリ解放時に特定のバイト列でフィルを行うことがあります。 4 バイトの LSB が 1 となる文字列で埋めることが多いようです。 これにより、リーク時の原因究明・リークの発見が早まります。 メモリダンプから、解放されたメモリと確保中のメモリが簡単に 区別できる利点もあります。
 
シュリンク
 
一度確保したメモリのサイズを縮めます。無駄なメモリ浪費を減らすためです。
 
ガーベージコレクション
 
正確にはガーベージコレクションの一機能のみですが、断片化の起きた状態で 確保されたメモリをヒープの頭から詰まるように再配置します。そのメモリ へのポインタを持っている全てのコードでその値の更新が必要となるため、 あまり使われない機能です。
 
ID ロック
 
確保時に ID を指定して、解放時にも同じ ID を指定しないと 解放できなくします。メモリリーク時の誤解放を防ぐことが可能です。
 
命名
 
デバッグに便利なように、確保時に名前を付けます。
 
検索機能
 
メモリに付けた ID や名前を元に、検索できる機能です。
 
開発機専用メモリの利用
 
ゲーム開発機器には、通常のユーザーが使用するゲーム機よりも多くのメモリを 積んでいるものがあります。その領域を使ってしまっている状態で開発を行うと、 開発機ではメモリが足りて動作するのにも関わらず、ゲーム機ではメモリ不足で 動かなくなってしまう事態が生じてしまうため、通常は使わないようにします。 そして、その代わりにデバッグアプリケーションやデバッグ情報 (メモリや タスクの関数呼び出しログなど) を置けるようにすることがあります。

戻る