如何在C ++中实现缓存?

时间:2012-08-27 14:26:30

标签: c++ caching memory-management

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

  • Foo
  • 检索ID x FooDB个对象
  • 如果对象 x FooDB中,则将其返回
  • 如果不是,请从HD加载,尝试将其存储在FooDB中以进行进一步查询
    • 有足够的可用内存:将其添加到FooDB
    • 没有足够的内存:通过从未使用的FooDB对象中删除一些空间(最早的查询时间戳)

我想为FooDB保留一些内存,但我无法分辨,可以存储多少Foo个对象,因为它们的大小不同。

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

修改

我的基本问题是:如何判断内存中std::map的大小?当然,包括存储在其中的所有堆对象。如何知道何时没有足够的内存部分?

2 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分: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);
}