【问题标题】:How can I get read-ahead bytes?如何获得预读字节?
【发布时间】:2011-02-13 12:27:56
【问题描述】:

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

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

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

【问题讨论】:

  • 您从磁盘获取的项目有多大?独立于预读,文件系统将以块大小(通常为 4KB)为单位从磁盘读取数据。因此,如果您的项目是 100 字节,也许您可​​以将问题简化为在同一块中显示项目——您无需借助花哨的界面即可计算出来。
  • 我想知道的不是操作系统读取的静态最小值,而是它为特定操作实际读取的字节数。

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


【解决方案1】:

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

    mincore() 返回一个向量 表示调用的页面是否 进程的虚拟内存是常驻的 在核心(RAM)中,因此不会导致 磁盘访问(页面错误)如果 参考。内核返回 有关居住地的信息 从地址addr开始的页面, 并继续 length 字节。

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

    【讨论】:

    • vmtouch 从命令行打印文件缓存统计信息 (*nix)
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 很抱歉让您失望了,但我对此没有具体用途。我在阅读 www.cs.sunysb.edu/~bender/pub/BenderHu-TODS07.pdf 和其他关于缓存遗忘的论文时突然想到。
    【解决方案4】:

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

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

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

    【讨论】:

    • 您关于确定页面是否常驻和实际阅读之间的竞争条件的观点是好的。但是,即使没有像我想做的那样做任何可疑的事情,您也会受到页面驱逐的摆布。一个普通的 fread 调用可以返回,并且内存页面在我使用它之前就消失了。
    • 是的 - 虽然不太可能 - 除非您面临严重的内存压力,否则操作系统不太可能分页最近使用的私有页面,因为它必须将它们写入磁盘。缓存页面或内存映射文件页面已经在磁盘上,因此操作系统丢失它们的成本要低得多。无论哪种方式,它似乎都不是胜利 - 您应该尽可能多地阅读并希望它尽可能免费。
    猜你喜欢
    • 2017-04-25
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多