Linux中的非缓冲I/O

11

我正在写大量数据,这些数据将在几周内不会再被读取。当我的程序运行时,机器上的可用内存量(显示为“free”或“top”)迅速下降,但我的应用程序使用的内存量并没有增加,其他进程使用的内存量也没有增加。

这导致我相信内存被文件系统缓存所消耗 - 由于我不打算长时间读取这些数据,我希望绕过系统缓冲区,使我的数据直接写入磁盘。我并没有改进性能或成为超级忍者的梦想,我的希望是给文件系统一个提示,告诉它我不会很快回来获取这些内存,因此不要花费时间为这些情况进行优化。

在Windows上,我面临着类似的问题,并通过 FILE_FLAG_NO_BUFFERING|FILE_FLAG_WRITE_THROUGH 解决了这个问题 - 机器的内存没有被我的应用程序占用,并且机器在一般情况下更易用。我希望能够复制我看到的改进,但在Linux上。在Windows上,有按扇区大小写入的限制,对于我测量到的收益,我对此限制感到满意。

在Linux中是否有类似的方法?

3个回答

7
我想到的与您提到的Windows标志最接近的等效物是使用 open(2) 标志 O_DIRECT | O_SYNC 打开您的文件:
   O_DIRECT (Since Linux 2.4.10)
          Try to minimize cache effects of the I/O to and from this file.  In
          general this will degrade performance, but it is useful in special
          situations, such as when applications do their own caching.  File I/O
          is done directly to/from user space buffers.  The O_DIRECT flag on its
          own makes at an effort to transfer data synchronously, but does not
          give the guarantees of the O_SYNC that data and necessary metadata are
          transferred.  To guarantee synchronous I/O the O_SYNC must be used in
          addition to O_DIRECT.  See NOTES below for further discussion.

          A semantically similar (but deprecated) interface for block devices is
          described in raw(8).

当然,如果你想确认这个标志是否符合你的要求,我找到了这篇有趣的文章,告诉你不使用缓冲I/O是一个坏主意,Linus将其描述为“脑损伤”。根据那篇文章,你应该使用madvise()来告诉内核如何缓存页面。可能会因人而异。


6
您可以使用O_DIRECT,但在这种情况下,您需要自己进行块IO;您必须按照FS块大小的倍数和块边界进行写入(可能不是强制性的,但如果您不这样做,性能会变得非常低,因为每个不对齐的写入都需要先读取)。
另一种几乎没有影响的方法是,在不使用O_DIRECT的情况下停止阻止您的块使用OS缓存,即使用posix_fadvise(fd,offset,len,POSIX_FADV_DONTNEED)。在支持它的Linux 2.6内核下,这将立即从缓存中丢弃(干净的)块。当然,您需要首先使用fdatasync()或类似的函数,否则块可能仍然是脏的,因此不会从缓存中清除。
可能每次写入后都调用fdatasync()和posix_fadvise( ... POSIX_FADV_DONTNEED) 是一个不好的主意,而是等到您完成了合理数量的写入(50M、100M之类的)。
总之,
- 在每个(重要块)写入后, - 调用fdatasync,然后是posix_fadvise( ... POSIX_FADV_DONTNEED) - 这将将数据刷新到磁盘并立即从OS缓存中删除它们,为更重要的事物留出空间。
一些用户发现,类似快速增长的日志文件可以轻松地将“更有用”的内容从磁盘缓存中清除,这会大大降低需要具有大量读取缓存但也快速写入日志的框的缓存命中率。这是此功能的主要动机。
然而,像任何优化一样,
a) 您不会需要它
b) 尚未实施时,请勿使用

2
当我的程序运行时,机器上的可用内存数量会很快下降。为什么这是个问题呢?可用内存是指没有任何有用目的的内存。当它被用于缓存数据时,至少还有可能有用。如果你的程序请求更多内存,文件缓存将是首先被清理的东西。Linux知道它可以随时从磁盘重新读取那些数据,所以它会回收内存并给它一个新的用途。确实,默认情况下,Linux会等待大约30秒(无论如何,这就是以前使用的值)才会将写入刷新到磁盘。你可以通过调用fsync()来加速此过程。但是一旦数据已经写入磁盘,保留数据缓存的成本几乎为零。考虑到你只是向文件中写入而不是从中读取,Linux可能会猜测这些数据最好被清除,而不是其他缓存的数据。因此,除非你已经确认这是一个性能问题,否则不要浪费精力进行优化。

1
只是因为缓存被用于永远不会被使用的东西,才导致了问题。这个缓存本来可以被其他人使用,而我现在看到了增加的 I/O。 - stuck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接