如何创建一个C++对象的内存映射列表

3

我有一段时间没有做C++了,对于以下最佳实现方法我有些生疏:

我们有一个数据库,存储大量的“对象”。 我正在考虑一种方法来将所有这些对象的完整列表加载到内存中,但由于这些对象的大小和数量,实际上将它们全部放在内存中是不可行的。 相反,我想要一个“内存映射文件”系统,在访问时按需加载对象。 换句话说,让操作系统或类似的东西管理应该在内存中的对象,类似于操作系统决定哪些文件段应分页到内存中。 有人能给我提示如何实现吗?


你使用哪个操作系统? - Some programmer dude
如果您使用的是Windows系统,请查看CreateFile()CreateFileMapping()MapViewOfFile()函数。 - Remy Lebeau
抱歉,我忘了提到我正在使用FreeBSD,但我希望能够将其移植到任何*nix平台。 - esotechnica
这个问题太模糊了,无法回答。我只知道你在数据库中有对象,它们对于RAM来说太大了。你的问题中没有提供任何其他细节。 - marinara
4个回答

1
如果你忘记了 C++,可以采用简单方法。
你提到“对象”;我将其视为“用户数据”,而不是实际的序列化 C++ 类。
无论如何,内存映射文件只是一个文件。你将从文件中读取,操作系统不会为你解决问题。
我的建议是保持简单。将“对象”作为常规文件 I/O 实现。然后,一旦实现正常工作,可以通过使用内存映射文件来提高性能。
至于设计模式, 我会设计一个 CObject 类,由 CDataBase 类创建。CDataBase 将知道文件(数据库)中每个对象的位置,并根据需要创建 CObjects(从文件中读取它们)。
祝你好运。

嗨,感谢您的回复。当我说“内存映射文件”时,我并不是真正意味着那个,我只是用这个类比来描述我试图做的事情的要点。是的,当我说“对象”时,我指的是存储在SQL表中的数据,因此我无法使用基于文件的方法。 - esotechnica

1

提醒一下 - 如果您有大量存储在 SQL 表中的对象想要任意加载到内存中,那么它很可能会在多个方面变慢:对数据库的访问次数过多(尝试使用最少的查询),太多的构造函数调用(使用内存池)等等...

...但是您需要逐步进行 - 首先看看是否可以将 SQL 中的记录读入已实例化的对象中。最佳速度优化将在您组织数据以最小化对 DB 的访问和最小化构造函数调用方面。

请注意,内存映射解决方案将代替 SQL 表 - 它将更快,但比 SQL 不够灵活,并且您将面临双重维护的问题:SQL 中的数据必须与您的内存映射文件保持同步。


嗨,这正是我所关心的问题。基本上,我想只创建一个对象(即从数据库中读取数据到对象的适当成员)。然后,类似于未被最近使用的内存页面被写入备份存储器一样,我希望以某种方式对这些对象执行相同的操作。这样,如果将对象“分页”到磁盘文件中,它只需要从磁盘读取对象的二进制表示,并指向它。这将避免从SQL等重新加载对象的缓慢开销。也许这不可能/容易做到? - esotechnica

0

我认为这仅适用于打开文件,不幸的是我的数据存储在 SQL 表中。 - esotechnica

0

因此,根据您的对象大小,您可以将它们存储在哈希映射中,该映射保留LRU列表并开始将对象逐出到文件,同时在映射中保留键和文件偏移量。这样,当您确实需要从磁盘上拉回它们时,只需进行一次搜索和读取即可获取对象。如果您想要预分配固定大小的文件,则可以将它们映射到内存中,您的偏移量将成为另一个指针。

这是Riak数据库初始存储方式的简化版本,他们在网站[1][2]上有一些设计文档。仅当您的对象大于键,以便所有键都可以轻松地放入内存中,但对象不行时,才能发挥最佳效果。

Cassandra数据库使用类似其“键缓存”的技术[3]。

您还可以查看类似Berkly DB的本地存储解决方案。

[1] : http://wiki.basho.com/Concepts.html#Data-Storage
[2] : http://downloads.basho.com/papers/bitcask-intro.pdf
[3] : http://www.datastax.com/dev/blog/maximizing-cache-benefit-with-cassandra


太棒了,这正是我所思考的事情,谢谢! - esotechnica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接