2

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

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

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

4

4 回答 4

6

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

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

mincore()返回一个向量,指示调用进程的虚拟内存的页面是否驻留在核心 (RAM) 中,因此如果被引用,则不会导致磁盘访问(页面错误)。addr内核返回有关从 address 开始并持续length字节的页面的驻留信息。

这里当然有一个竞争条件——mincore()可以告诉你一个页面是常驻的,但它可能会在你访问它之前被换掉。 生活吧

于 2010-04-29T01:38:38.443 回答
2

你是从一个错误的假设开始的。至少在 Linux 上,操作系统会尝试找出程序的访问模式。如果您按顺序读取文件,内核将按顺序预取。如果你在文件中跳转很多,内核可能一开始会感到困惑,但随后它会停止预取。

因此,如果您实际上按顺序访问文件,您就知道可能预取了什么:下一个数据块。如果您是随机搜索,则附近可能没有其他任何东西被预取。

尝试以不同的方式解决这个问题。在调用 read() 获取您需要的信息之前,调用fadvise()让操作系统知道您希望它开始加载什么。

我也很想知道您使用的哪种应用程序可以通过仅对碰巧在文件缓存中的数据进行操作来正确运行。我觉得如果您发布更多信息,我们可以找到满足您需求的好方法。

于 2010-04-28T19:49:23.087 回答
1

我可以使用什么 API 来找出操作系统缓存中的内容?

对于任何 posix 系统,当然没有标准的方法可以做到这一点,而且我不知道任何特定于 Linux 的非标准方法。您唯一可以(几乎)确定的是文件系统将读取页面大小的倍数,通常为 4kB。因此,如果您的读取量很小,您可以很可能(尽管不确定)知道周围页面中的数据在内存中。

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

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

最后,我赞同@Karmastan 的建议:解释你想要达到的更广泛的目标。可能有一种方法可以做到这一点,但您建议的方法不是。

于 2010-04-28T19:53:03.997 回答
1

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

同样的事情也适用于确定一个页面是否是常驻的。一旦你发现当其他线程需要内存来做其他事情时,答案可能会改变。

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

于 2010-04-28T19:26:56.923 回答