5

假设,我有一个非常大的std::map< unsigned int, Foo > FooDB,它在内存中保存Foo对象,可以通过它们的 ID 检索。现在可能有Foo比可用内存更多的对象来存储它们。所以我想有以下构造:

  • 检索FooID为x的对象FooDB
  • 如果对象x在 中FooDB,则返回它
  • 如果不是,请从 HD 加载它,尝试将其存储起来以FooDB供进一步查询
    • 有足够的可用内存:将其添加到FooDB
    • 内存不足:通过FooDB从未使用的对象中删除来释放一些空间(最旧的查询时间戳)

我想为 保留一些内存,但FooDB我不知道其中可以存储多少个Foo对象,因为它们的大小不同。

关于如何实现这一点的任何想法?

编辑

我的基本问题是:我怎样才能知道 astd::map的内存大小?当然,存储在其中的所有堆对象都包括在内。我怎么知道内存不足的部分何时到达?

4

2 回答 2

5

据我所知,除了 sizeof() 之外,没有办法询问对象的大小。您说 sizeof() 不起作用,因为 Foo 对象没有固定大小。在这种情况下,如果您可以修改 Foo,那么您的 Foo 类可能可以在内部跟踪其内存占用。如果你不能修改 Foo,你也许可以编写一个可以推断内存占用的外部函数。

从根本上说,语言/编译器/运行时很难知道动态大小的对象有多大,因为它不知道哪些分配属于该对象。一个简单的解决方案,只是递归地总结它的成员指向的所有东西,将在任何具有指向它不“拥有”的对象的指针上失败。另一个简单的解决方案是跟踪在构造函数启动和返回之间完成的所有分配,对于在调用构造函数后进行分配的任何事情都会失败。

您可能只想使用 Foo 的数量作为缓存限制,而不是内存大小。除非您对整个系统的内存可用性和使用情况了解很多,否则基于内存大小的上限也是任意的。如果您对整个系统的内存使用情况了解很多,您可以只使用整体内存可用性来确定何时从缓存中释放对象。

于 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 回答