Upload
dada246
View
4.423
Download
1
Embed Size (px)
Citation preview
高度に最適化された移植可能なメモリマネージャ
@DADA246
自己紹介• ゲームプログラマやってます
• 得意分野 C++,C#,GPU,javascript,PHP• 低レベル係とか描画関係とか CI とか web
とか
• Steam 、 Origin 、 iPhone で海外ゲームを遊んでいます
はじめに• 元ネタは Game Engine Gems2 のA Highly Optimized Portable Memory Manager です
• Kindle Edition が $55.92 で買えます
アジェンダ• ゲームでのメモリマネージャについて• Small Block Allocator• Medium Block Allocator• Large Block Allocator
メモリマネージャ• メモリマネージャは重要
• 悪いメモリマネージャは処理速度の低下や、フラグメンテーションによるクラッシュを引き起こす
→ 枯れたコードを参考にする→dlmalloc
dlmalloc
• Doug Lea’s malloc• http://g.oswego.edu/dl/html/malloc.html
• 非常に良い実装だが、汎用的である→ ゲーム用にカスタマイズする
dlmalloc
• 確保サイズごとにリストが用意されている
24
16
32
確保サイズ (byte) チャンク
…
2^31
40
ゲーム用メモリマネージャ• キャッシュラインを意識する• 空き領域を検索しない• 高速なアロケート• デバッグの容易性• バッファオーバーフローしても管理領域が
壊れにくい• フラグメンテーションが起きにくい
管理領域
確保領域 A
管理領域 A
確保領域 B
管理領域 B
確保領域 A
確保領域 B
管理領域 A管理領域 B
確保領域 A がバッファオーバーフローすると、管理領域を破壊してしまう→ バグの追跡が困難になる
確保領域 A がバッファオーバーフローしても、管理領域は破壊されない
○✕
フラグメンテーション• 大きなメモリアロケーションの中に小さ
なメモリアロケーションが混ざると発生する
空き使用
空き
空き
使用
空き
使用alloc x2 free
フラグメンテーション対策• ページングを活用するWindows の VirtualAlloc()
• VirtualAlloc は処理が重いので、多発する小さなメモリ確保には適さない
→ メモリ確保量によってアロケータを分ける
複数のアロケータ
Small Block Allocator
Medium Block Allocator
Large Block Allocator
0メモリ確保量 (byte)
256
4096
メモリ確保頻度少ない
多い
基本設計• 各種アロケータはページ単位で動作する→x86 を考えて 4kbyte 単位にする
• ページ同士はリンクリストで管理する
Small Block Allocator
• 4kbyte/ ページで構成• 32byte/block
• 1 ページごとに管理領域として1ブロック使用→127 ブロックの空き
Small Block Allocator
• 確保サイズごとにページを用意する
24
16
32
40
確保サイズ (byte)
…256
管理領域
struct Header{ uint32_t emptyBlockBit[4];// 空きブロックのビットマスク uint32_t emptyBlockCount;// 空きブロック数 ( ベリファイ用 ) uint32_t blockSize;// ブロックサイズ uint32_t* pPrePage;// 前ページへのポインタ uint32_t* pNextPage; // 次ページへのポインタ}
• 32byte=1 ブロック• ブロックの空き状態をビット列で管理す
る
alloc
• 空きブロックのあるページを探す
• 空きブロックがあるページが見つかったら、空きブロックのビットマスクをスキャンして確保アドレスを確定する
→ x86 なら bsf 命令が使える
• 空きブロックが無かったら OS からページアロケーションする
ページ管理• 空き領域の有無でページのリンクリストを分
ける→ 空き領域を検索しない
24
16
32
空き領域無し
…
24
16
32
空き領域あり…
free
• free するアドレスからページを算出する→ 管理領域を見つけられる
• 空きブロックがなくなったら OS にページを返す
int32_t pageAddress=(address/4096)*4096;
パフォーマンス• x86 のキャッシュラインは 64byte→ Small Block Allocator の管理領域は 32byteなので、キャッシュラインをまたがない
• 1 ページ 4kbyte なので、今時の L1 キャッシュに載る
Medium Block Allocator
• 16kbyte/ ページで構成• 128byte/block
• 1 ページごとに管理領域として1ブロック使用
Medium Block Allocator
• 1 ページで複数の確保サイズを扱う→ メモリの利用効率を上げるため
512
384
640
768
確保サイズ (byte)
…
4096
alloc と free
• Small Block Allocator とほぼ同じ
• alloc は可変長のメモリサイズを扱っているため、 Small Block Allocator よりは処理が重め
• free は空きブロックがなくなったら OS にページを返す
ページ管理• どれだけ空き領域があるかをリンクリス
トで管理する→ 空き領域のあるページを高速に探す
128
0
256
384
空き領域 (byte)
…
Large Block Allocator
• alloc ごとにページアロケーションする→ 大きなメモリ確保なので発生頻度が低い
• シンプルなリンクリストで実装できる
応用• Small Block Allocator のアプローチで
Medium サイズのメモリ確保も行えるのでは?
• 1 ブロックサイズをメモリ確保サイズによって変えても良いのでは?
まとめ• dlmalloc などの枯れたコードを参考にす
る
• ページアロケーションでフラグメンテーションを抑える
• アロケーションサイズによってアルゴリズムを分けることで高速化する
まとめ• メモリマネージャを扱ってみました
• 良いメモリマネージャがあれば高レベルライブラリも使いやすくなります
次のステップ• マルチスレッド化http://www.gdcvault.com/play/1014602/Multicore-Memory-Management-Technology-in
• メモリデバッグツール
Question?
ご清聴ありがとうございました