如何获得预读字节?

时间:2010-04-28 19:20:03

标签: windows linux operating-system virtual-memory pagefile

操作系统从磁盘读取的数量超过程序实际请求的数量,因为程序将来可能需要附近的信息。在我的应用程序中,当我从磁盘中获取项目时,我想显示元素周围的信息间隔。我要求和显示的信息量和速度之间存在权衡。但是,由于操作系统已经读取了超过我的请求,因此访问内存中的这些字节是免费的。我可以使用什么API来找出操作系统缓存中的内容?

或者,我可以使用内存映射文件。在这种情况下,问题减少到找出页面是否交换到磁盘。这可以在任何常见的OS中完成吗?

编辑:相关文件http://www.azulsystems.com/events/mspc_2008/2008_MSPC.pdf

4 个答案:

答案 0 :(得分:5)

你确实可以使用你的第二种方法,至少在Linux上。 mmap()文件,然后使用mincore()函数确定哪些页面驻留。从手册页:

  

int mincore(void *addr, size_t length, unsigned char *vec);

     

mincore()返回一个向量   表示是否呼叫的页面   进程的虚拟内存是驻留的   在核心(RAM),所以不会导致   磁盘访问(页面错误)if   引用。内核返回   居住信息   从地址addr开始的网页,   并继续length个字节。

当然有一个竞争条件 - mincore()可以告诉你一个页面是常驻的,但它可能会在您访问之前被换出。 C'est la vie

答案 1 :(得分:2)

你是从一个错误的推定开始的。至少在Linux上,操作系统会尝试找出程序的访问模式。如果按顺序读取文件,内核将按顺序进行预取。如果你经常跳转文件,内核可能会先被混淆,但它会停止预取。

因此,如果您实际 依次访问您的文件,您就知道可能预取的内容:下一个数据块。如果你是随机搜索的,可能在附近没有别的东西被预取。

尝试以不同的方式处理此问题。在调用read()以获取所需的信息之前,请调用fadvise()让操作系统知道您想要它开始加载...

我也很想知道你正在使用哪种类型的应用程序只能操作恰好位于文件缓存中的数据才能正确运行。如果您发布更多信息,我觉得我们可以找到满足您需求的好方法。

答案 2 :(得分:1)

当然无法在Windows上完成。在Windows上,预读行为取决于操作系统,即使它可以告诉你它已经预读了多少,它对你没有任何好处,因为一旦你发现,内存页面就是用于缓存的内容可以用于其他用途。

同样的事情是确定页面是否驻留。一旦你发现答案可能会改变,当一些其他线程需要内存以寻找别的东西时。

如果你真的想在Windows上做一些事情,你可以自己关闭缓冲和管理缓冲区。这是最快的IO路径,但它也是最复杂的 - 您必须非常小心,并且操作系统通常仍然可以做得更好。

答案 3 :(得分:1)

  

我可以使用哪些API来查找操作系统缓存中的内容?

对于任何posix系统来说肯定没有标准的方法来做这件事,我也不知道任何特定于Linux的非标准方式。你几乎可以肯定知道的唯一事情是文件系统将读取多个页面大小,通常为4kB。因此,如果您的读取很小,您很可能(尽管不确定)知道周围页面中的数据是在内存中。

我想,你可以做一些棘手的事情,例如计算读取系统完成的时间。如果速度很快,即100微秒或更短,则可能是缓存命中。一旦它达到一毫秒左右,它可能是一个缓存未命中。当然,这实际上对你没有多大帮助,而且非常脆弱。

请注意,一旦文件系统将数据复制到用户缓冲区,就可以立即丢弃从磁盘保存数据的缓冲区。它可能不会立即执行此操作,但您无法确定。

最后,我第二个@ Karmastan的建议:解释你想要实现的更广泛的目标。可能有办法做到这一点,但你建议的那个不是它。