在 Linux 上使用 O_DIRECT

在 Linux 上使用 O_DIRECT

如果这个问题太面向程序员,请告诉我。我想知道是否有人熟悉 Linux 2.6 上 open() 系统调用的 O_DIRECT 标志? Linus 贬低了它的用途,但是高性能文件写入似乎表明了它的用途。我想知道任何现实世界的经验和建议。

更多信息:我正在使用的应用程序维护自己的缓存,这样做可以获得平均 5 倍或更多的速度提升。当写入文件时,缓存的内容必须写出到文件系统缓存,这似乎是多余的并且存在性能问题。

答案1

好吧,你问的是经验,这使得这个问题有点主观和争论,但还可以。

Linus 说,提到人们通常归因于 O_DIRECT 的用途,对于这些用途,IMO Linus 基本上是正确的。即使您进行直接 I/O,也无法将数据直接从设备传输到程序语句,您需要一个缓冲区(由程序或设备填充)并通过系统调用传输到另一端。此外,为了提高效率,您不会想重读刚刚读过的内容,以防您再次需要它。所以你需要某种缓存...而这正是内核在没有 O_DIRECT 的情况下提供的页面缓存!为什么不使用它呢?它还有一个好处,如果更多进程想要同时访问同一个文件,那么 O_DIRECT 将是一场灾难。

话虽如此,O_DIRECT 有它的用处:如果由于某种原因你需要直接从块设备获取数据。它与性能无关。

使用 O_DIRECT 来提高性能的人通常来自具有糟糕页面缓存算法的系统,或者没有 POSIX 建议机制,甚至是盲目地重复别人说过的话的人。为了避免这些问题,O_DIRECT 是一个解决方案。 Linux,OTOH,的理念是你应该解决真正的底层问题,而底层问题是操作系统在页面缓存方面做得不好。

我用的是O_DIRECT一个简单的 cat 实现来查找我的机器中的内存错误。这是 O_DIRECT 的一种有效用途。这与性能无关。

答案2

实际上,O_DIRECT 需要避免其中任何一个

  • 缓存污染— 有时您知道缓存的开销是没有意义的,例如,在处理非常大的文件时,比如 64 GiB,而 RAM 只有 2 GiB。用户决定验证的 32 GiB Torrent 文件似乎不适合缓存。这只是额外的活动,有其自身的开销。它可能会导致一些真正有用的数据从缓存中被删除。
  • 双缓存— 例如,某些 RDBMS(例如 MySQL)允许定义自己的缓存。据推测,数据库比内核虚拟内存更了解如何缓存以及缓存什么,而内核虚拟内存对 SQL 规划等一无所知。

——看起来这并不好。并不O_DIRECT意味着要更快,通常情况并非如此

答案3

它与性能有很大关系。

一个有趣的例子是在 mongodb 中使用 mmap 引擎。正如其他人所说,O_DIRECT 最好使用,因为在一段时间内不太可能读取数据。在 mongodb 中,数据库日志是使用 O_DIRECT 写入的,而数据和索引写入则由页面缓存机制(pdflush)处理,因为虽然 O_DIRECT 提供的带宽更少,但它也意味着更少的延迟,从而减少了发生意外时的数据丢失。意外中断(内核恐慌、磁盘或电源故障)。请注意,在 O_DIRECT 写入提交到非易失性存储之前仍然存在缓冲,这只是减少了数据丢失。

O_DIRECT 的另一个重要特性是它提供了对顺序的写入。同样,它不保证写入的顺序(除非您有一个非易失性缓存磁盘控制器并且正在使用 fifo 调度程序,但这些都有其自身的复杂性)。因此,尽管 mysql 将 O_DIRECT 用于其数据/索引以及日志记录,但可以预期后者通常会首先提交。

但重要的是要记住 O_DIRECT 破坏了资源分配的公平性。应用程序加速的原因之一是它会减慢其他东西的速度。

答案4

关于@Juliano 已经说过的话。

检查posix_fadvise真正的问题是否是底层文件系统的缓存算法的错误行为,您可以尝试给它建议,您将如何使用文件系统。对于良好实现的 fs,它应该会提高性能。 (这是涉及类似考虑因素的另一个主题的链接https://stackoverflow.com/a/3755818/544721

相关内容