内存映射BIG文件时应注意哪些陷阱?

问题描述

| 我有一堆大文件,每个文件可以超过100GB,数据总量可以是1TB,它们都是只读文件(只是随机读取)。 我的程序在具有大约8GB主内存的计算机上对这些文件进行少量读取。 为了提高性能(不进行seek()和不进行缓冲区复制),我考虑使用内存映射,基本上是对整个1TB数据进行内存映射。 尽管起初听起来很疯狂,但作为主内存<<磁盘,了解虚拟内存的工作原理后,您应该会发现在64位计算机上应该没有问题。 从磁盘读取的所有页面以回答我的read()都将从操作系统中视为“干净”,因为这些页面永远不会被覆盖。这意味着所有这些页面都可以直接进入操作系统可以使用的页面列表,而无需写回磁盘或交换(清洗它们)。这意味着操作系统实际上可以仅将LRU页存储在物理内存中,并且当该页不在主内存中时仅可以操作reads()。 由于巨大的内存映射,这将意味着不进行交换,也不增加I / O。 这是理论;我正在寻找的是所有人,他们在实际生产中都尝试过或使用过这种方法,并且可以分享他的经验:这种策略是否存在实际问题?     

解决方法

您所描述的是正确的。使用64位操作系统,您可以将1TB的地址空间映射到文件,并让操作系统管理对该文件的读写。 您没有提到您使用的是哪种CPU体系结构,但是对于大多数页面结构(包括amd64),CPU都会在每个页面表条目中保留一点有关是否已写入页面中的数据的信息。操作系统确实可以使用该标志来避免将尚未被修改的页面写回到磁盘。 仅仅因为映射很大,IO不会增加。您实际访问的数据量将决定这一点。大多数操作系统,包括Linux和Windows,都具有统一的页面缓存模型,其中缓存的块使用与内存映射页面相同的物理内存页面。我不希望操作系统使用内存映射比使用缓存的IO使用更多的内存。您将直接访问缓存的页面。 您可能会担心的是将修改后的数据刷新到磁盘上。我不确定您的操作系统具体采用了什么策略,但是从修改页面到操作系统实际将数据写入磁盘的时间可能比您预期的要长得多。如果一定要在一定时间内将数据写入磁盘,那么请使用刷新API强制将数据写入磁盘。 我过去没有使用过那么大的文件映射,但是我希望它能很好地工作,至少值得一试。