これは良い考えだとは思いませんが、1 つの解決策は、さまざまなログ2サイズのバケットを事前に割り当てておくことです。愚かな疑似コードです。
class Allocator {
void* malloc(size_t size) {
int bucket = log2(size + sizeof(int));
int* pointer = reinterpret_cast<int*>(m_buckets[bucket].back());
m_buckets[bucket].pop_back();
*pointer = bucket; //Store which bucket this was allocated from
return pointer + 1; //Dont overwrite header
}
void free(void* pointer) {
int* temp = reinterpret_cast<int*>(pointer) - 1;
m_buckets[*temp].push_back(temp);
}
vector< vector<void*> > m_buckets;
};
(もちろんstd::vector
、 を単純な配列 + カウンターに置き換えることもできます)。
編集:これを堅牢にする(つまり、バケットが空の状況を処理する)には、何らかの形式の分岐を追加する必要があります。
EDIT2:これは小さなブランチレスlog2
関数です:
//returns the smallest x such that value <= (1 << x)
int
log2(int value) {
union Foo {
int x;
float y;
} foo;
foo.y = value - 1;
return ((foo.x & (0xFF << 23)) >> 23) - 126; //Extract exponent (base 2) of floating point number
}
これにより、33554432 バイト未満の割り当てに対して正しい結果が得られます。より大きな割り当てが必要な場合は、double に切り替える必要があります。
これは、浮動小数点数がメモリ内でどのように表現されるかへのリンクです。