LoginSignup
13
14

More than 5 years have passed since last update.

C++の簡単なメモリアロケータ実装

Last updated at Posted at 2017-09-02

はじめに

ゲーム開発においてメモリ割り当てコストが気になったので検証・勉強もかねて独自のメモリアロケータを実装しました。

設計

  • メモリ割り当て時間の短縮を重視
  • 固定長のメモリブロックをあらかじめ確保しておき、メモリ確保時に適切なブロック領域から割り当てを行う。
  • ブロックサイズ8,16,32,64,128,256 (バイト)
  • ブロック数各1024個。オーバーしたら自動で拡張
  • 257バイト以上は通常のmallocを呼び出す
  • 未割当領域のアドレスをスタックで管理を行う。

実装

プロジェクト一式
Github

簡潔に書くとこのような実装方法です。

int blockSize = 8;
int blockNum = 1024;
void* memoryPool = new char[blockSize * blockNum];
Stack<void*> unUsedPoolStack;

for(int i = 0; i < blockNum; i++){

    //blockSize(8バイト)ごとにアドレスをStackに詰める
    unUsedPoolStack.push(memoryPool + i * blockSize);
}

void *operator new (size_t size) {
    void* p = nullptr;
    if(size <= 8){
        //Stackからアドレスを取り出し
        p = unUsedPoolStack.top();
        unUsedPoolStack.pop();
    }
    return p;
}

void operator delete (void* p, size_t size) {
    if(size <= 8){
        //使い終わったのでStackにアドレスを追加
        unUsedPoolStack.push(p);
    }
}

結果

通常のnewと自作のnewでの計測結果
12バイトのクラスを100万個割り当てを行い、それを10回繰り返した平均時間から実行速度割合を算出しました。

newTimeRate:newのみを100万回実行した平均
deleteTimeRate:deleteのみを100万回実行した平均
new/deleteTimeRate:newとdeleteを100万回実行した平均

Debug実行時
newTimeRate:51.1945%
deleteTimeRate:33.0951%
new/deleteTimeRate:43.4589%

Release実行時
newTimeRate:19.1974%
deleteTimeRate:7.625%
new/deleteTimeRate:7.99777%

上記からnewだけ見てもDebug時で2倍、Release時で5倍の速度が出せることがわかり、
200行程度のコードでこれだけ早くなったので満足いく結果になりました!
ただ、std::allocatorは実装していないためSTLにも適応する場合は追加実装が必要です。

13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14