5

ID で取得できるオブジェクトをメモリにstd::map< unsigned int, Foo > FooDB保持する非常に大きながあるとします。Foo現在、Fooそれらを格納するために使用できるメモリよりも多くのオブジェクトが存在する可能性があります。したがって、次の構成が必要です。

  • からFooID xのオブジェクトを取得するFooDB
  • オブジェクトxが にある場合FooDB、それを返します
  • FooDBそうでない場合は、HD からロードし、さらなるクエリ のために保存してみてください
    • 十分なメモリが利用可能です: 追加してくださいFooDB
    • FooDB十分なメモリがありません:使用されていないオブジェクト (最も古いクエリのタイムスタンプ)から削除して、いくつかの領域を解放します

にメモリを確保したいのですが、オブジェクトのサイズが異なるため、そこに格納できるオブジェクトFooDBの数がわかりません。Foo

これを実装する方法についてのアイデアはありますか?

編集

私の基本的な問題はstd::map、メモリ内の a のサイズをどのように知ることができますか? もちろん、そこに格納されているすべてのヒープ オブジェクトが含まれます。メモリが不足している部分に到達したことをどのように知ることができますか?

4

2 に答える 2

5

As far as I know, there's no way to ask an object what its size is, other than sizeof(). You said that sizeof() won't work because the Foo objects don't have a fixed size. In that case, if you can modify Foo, then maybe your Foo class can keep track of its memory footprint internally. And if you can't modify Foo, you might be able to write an external function that can deduce the memory footprint.

Fundamentally, it would be very difficult for the language/compiler/runtime to know how big a dynamically-sized object is because it doesn't know which allocations belong to the object. A simple solution, just recursively sum all of the things that it's members point to, will fail on anything that has a pointer to an object that it doesn't "own". Another simple solution, to keep track of all of the allocations done between when the constructor starts and when it returns, will fail for anything that makes allocations after the constructor is called.

You might want to just use the number of Foo's as your cache limit instead of the memory size. Unless you know a lot about the memory availability and usage of the entire system, a cap based on memory size would be arbitrary as well. And if you know a lot about the memory usage of the entire system, you could just use the overall memory availability to determine when to release objects from the cache.

于 2012-08-27T15:59:24.317 に答える
4

それはかなり簡単です。

FooDB のメモリ内の各 Foo インスタンスへの参照を、年齢順に並べ替えられたリンク リストに配置するだけです。

新しい項目を初めてメモリにロードするときは、それをリストの先頭に追加します。

項目を読み取り/変更するときは、リストの中央からリストの先頭に移動します。

古いアイテムを削除して、リストの後ろからスペースを空ける必要がある場合。

例えば:

typedef shared_ptr<Foo> PFoo;

class Foo
{
    ...
    list<PFoo>::iterator age;
};

typedef map< unsigned int, PFoo > FooDB;
FooDB foodb; 

list<PFoo> ages;

void LoadFoo(PFoo foo)
{
    ages.push_front(foo);
}

void ReadFoo(PFoo foo)
{
    ...
    ages.erase(foo->age);
    ages.push_front(foo);
}

void MakeSpace()
{
    PFoo foo = ages.back();
    ages.pop_back();
    DeleteFoo(foo);
}
于 2012-08-27T14:38:18.113 に答える