内存映射文件的优点是什么?

我一直在研究一个项目的内存映射文件,并会感谢来自以前使用过的人的任何想法,或决定不使用它们,为什么?

我特别关心以下几点,重要性如下:

  • 并发
  • 随机访问
  • 性能
  • 使用方便
  • 可移植性

我认为这样做的好处是可以减less传统读取文件的方法所需的复制数据量。

如果您的应用程序可以在内存映射文件中“就地”使用这些数据,则它可以进入而不被复制; 如果您使用系统调用(例如Linux的pread()),那么通常会涉及内核将数据从其自己的缓冲区复制到用户空间。 这种额外的复制不仅需要时间,而且通过访问这些额外的数据副本来降低CPU的高速caching的有效性。

如果实际上必须从光盘读取数据(如在物理I / O中),则操作系统仍然必须读取它们,页面错误可能不是比系统调用更好的性能方面,但是如果它们不要(即已经在OScaching中),性能理论上应该好多了。

不利的一面是,没有内存映射文件的asynchronous接口 – 如果你试图访问一个没有映射的页面,它会产生页面错误,然后让线程等待I / O。


内存映射文件的明显缺点是在32位操作系统上 – 您可以轻松地用尽地址空间。

我已经使用内存映射文件来实现“自动完成”function,而用户正在键入。 我有超过100万的产品部件号存储在一个单一的索引文件。 该文件具有一些典型的标题信息,但文件的大部分是在键字段上sorting的固定大小logging的巨大数组。

在运行时,文件被映射到内存,转换为Cstruct数组,然后执行二进制search以查找与用户types匹配的部件号。 实际上只有less量的文件内存页面是从磁盘读取的 – 在二进制search期间,无论哪个页面被打中。

  • 并发 – 我有一个实现的问题,它有时会在相同的进程空间内多次存储映射文件。 我记得这是一个问题,因为有时系统找不到足够大的空闲块来映射文件。 解决scheme是只映射文件一次,并thunk所有的电话。 回想起来,使用全面的Windows服务将会很酷。
  • 随机访问 – 二进制search当然是随机访问和闪电快
  • 性能 – 查找速度非常快。 当用户input一个popup窗口显示匹配的产品部件号列表时,列表会在继续input时收缩。 打字时没有明显的滞后。

内存映射文件可以用来替代读/写访问,或支持并发共享。 当你将它们用于一个机制时,你也可以得到另一个机制。

而不是在文件中寻找和阅读,而是将其映射到内存中,并简单地访问您期望它们的位。

这可以非常方便,并根据虚拟内存接口可以提高性能。 由于操作系统现在可以pipe理这个以前的“文件I / O”以及所有其他程序存储器访问,并且可以(理论上)利用已经用于支持的分页algorithm等虚拟内存为您的程序的其余部分 。 但是,它确实取决于底层虚拟内存系统的质量。 我听过的一些轶事说,Solaris和* BSD虚拟内存系统可能比Linux的虚拟机系统有更好的性能改进 – 但是我没有经验数据来支持它。 因人而异。

当您考虑通过映射内存使用相同的“文件”进行多个进程的可能性时,并发性就出现了。 在读/写模型中,如果两个进程写入文件的同一区域,则可以确信进程的一个数据将到达该文件,并覆盖其他进程的数据。 你会得到一个或另一个 – 但不是一些奇怪的混合。 我不得不承认,我不确定这是否是任何标准所规定的行为,但这是你几乎可以信赖的。 (这实际上是后续问题!)

在映射的世界,相反,想象两个过程都“写”。 他们通过做“内存存储”来完成这个工作,最终导致O / S将数据分页到磁盘。 但是与此同时,重叠的写入可能会发生。

这是一个例子。 假设我有两个进程在写入1024个字节的8个字节。进程1正在写入'11111111',进程2正在写入'22222222'。 如果他们使用文件I / O,那么你可以想象,在O / S的内部,有一个满缓冲区的缓冲区和一个满缓冲区的缓冲区,两者都前往磁盘上的同一个地方。 其中一个将首先到达那里,另一个是第二个。 在这种情况下,第二个胜利。 但是 ,如果我正在使用内存映射文件方法,则进程1将进入4字节的内存存储,然后是另一个4字节的内存存储(让我们假设不是最大内存存储大小)。 过程2将做同样的事情。 基于进程运行的时间,您可以期望看到以下任一情况:

 11111111 22222222 11112222 22221111 

解决这个问题的方法是使用明确的互斥 – 这在任何情况下都是一个好主意。 无论如何,你在读/写文件I / O的情况下依靠O / S来做“正确的事情”。

分类互斥原语是互斥体。 对于内存映射文件,我build议你看一下内存映射的互斥锁,可以使用(例如)pthread_mutex_init()。

编辑一个问题:当你使用映射文件的时候,有一个诱惑在文件中embedded指向文件中数据的指针(思考保存在映射文件中的链表)。 你不想这样做,因为文件可能在不同的时间映射到不同的绝对地址,或者在不同的进程中。 而是使用映射文件中的偏移量。

并发将是一个问题。 随机访问更简单性能好对了不起。 使用方便。 不太好。 可移植性 – 不是太热。

我很久以前就把它们用在Sun系统上了,这些都是我的想法。