【问题标题】:The state of Linux async IO?Linux 异步 IO 的状态?
【发布时间】:2011-04-23 22:55:34
【问题描述】:

我在这里问是因为谷歌搜索会引导您在档案馆进行愉快的旅行,而不会提示当前状态是什么。如果你去谷歌看看,似乎异步 IO 在 2001 年到 2003 年风靡一时,到 2006 年,像 epolllibaio 这样的东西出现了; kevent 出现但似乎消失了,据我所知,仍然没有好的方法来混合基于完成和基于就绪的信号,异步 sendfile - 甚至可能的? - 以及单线程事件循环中的所有其他内容。

所以请告诉我我错了,一切都很美好! - 重要的是,要使用哪些 API。

Linux 在这方面与 FreeBSD 和其他操作系统相比如何?

【问题讨论】:

标签: linux asynchronous io


【解决方案1】:

这样的 AIO 仍然有些局限,上手时确实很痛苦,但是一旦你深入了解它,它在大多数情况下都可以工作。

在我看来,它有一些严重的错误,但这些确实是功能。例如,当提交一定数量的命令或数据时,你的提交线程会阻塞。我不记得这个特性的确切理由,但我当时得到的答复是“是的,当然,内核对其队列大小有限制,这是预期的”。如果您提交几千个请求,这是可以接受的……显然,某处必须有一个限制。从 DoS 的角度来看,这也可能是有意义的(否则恶意程序可能会通过发布十亿个请求来迫使内核耗尽内存)。但是,您仍然可以在“正常”数字(一百左右)中实际遇到这种情况,并且会出乎意料地打击您,这不好。另外,如果您只提交六个左右的请求并且它们有点大(几兆字节的数据),那么可能会发生同样的情况,显然是因为内核将它们分解为子请求。再说一遍,这有点道理,但看看文档没有告诉你,你应该期望读取 500 字节或 50 兆字节的数据没有区别(除了花费更长的时间)。

此外,似乎没有办法进行缓冲 AIO,至少在我的任何 Debian 和 Ubuntu 系统上都是这样(尽管我看到其他人抱怨完全相反,即实际上通过缓冲区进行的非缓冲写入) .从我在我的系统上看到的情况来看,AIO 只是在关闭缓冲的情况下才真正异步,这很可惜(这就是为什么我目前在内存映射和工作线程周围使用了一个丑陋的构造)。

任何异步的一个重要问题是能够在其上执行 epoll_wait(),如果您正在执行除磁盘 IO 之外的任何其他操作(例如接收网络流量),这一点很重要。当然有 io_getevents,但它并不是那么理想/有用,因为它只适用于一个单一的事情。

在最近的内核中,支持 eventfd。乍一看,它似乎毫无用处,因为不清楚它会以何种方式提供帮助。 然而,为了您的救援,有一个未记录的函数 io_set_eventfd 可以让您将 AIO 与一个 eventfd 相关联,它是 epoll_wait()-able。您必须深入研究标题才能了解它,但它肯定在那里,而且效果很好。

【讨论】:

  • 我认为这是指内核 AIO 而不是 POSIX AIO?
  • @JanusTroelsen:是的,就像问题一样,这是指内核 AIO (libaio)。 POSIX AIO 与其说是 Linux 功能,不如说是在librt 中使用线程池和标准同步 I/O 实现的库功能。令人惊讶的是,这在各个方面都比内核实现效果好多
  • @Damon:POSIX AIO 更容易,但你有什么证据表明它“工作得更好更好”?我的理解是,假设它被正确使用(O_DIRECT 在支持它的文件系统上),内核 AIO 速度更快,资源使用率更低(主要是因为它不需要创建和管理线程池)​​。当然,POSIX AIO 更具可移植性,但是当您使用任何一种技术时,您通常最关心性能和资源使用,而内核 AIO 应该更好。
  • @ShadowRanger:AIO 的要点是 异步 没有阻塞。 POSIX AIO 正好提供了这一点,内核 AIO 没有(顺便说一下,Windows 也没有!)。 “更快”不是 AIO 的优先事项,因为它通常不是更快,而是更慢。有明显的例外,例如顺序第一次,一次性从光驱读取,在这种情况下,AIO 确实快得多。在每个“正常”情况下,它都会慢几个数量级。不过没关系,因为 asynchronous 是我们想要的和重要的,而不是 fast。现在,内核 AIO 在不适当的时候阻塞,......
  • ... 而 POSIX AIO 没有,这要好得多。另外,它使用缓冲区缓存,因此(在正常情况下)也快得多。所以总而言之,即使 POSIX 是一个“尴尬的实现”,线程执行普通的普通读/写,它仍然好多更好。如果对缓冲区缓存的支持进入内核(提案已经提出十年左右,但据我所知仍未被接受),那么它可能在速度方面处于同等水平。
【解决方案2】:

异步磁盘 IO 是活跃的...它实际上得到支持并且现在工作得相当好,但有很大的局限性(但有足够的功能,一些主要用户可以有用地使用它 - 例如 MySQL 的 Innodb 在最新版本)。

异步磁盘 IO 是一种以非阻塞方式(在单个线程中)调用磁盘 IO 操作并等待它们完成的能力。这很好用,http://lse.sourceforge.net/io/aio.html 有更多信息。

AIO 足以让典型的应用程序(数据库服务器)能够使用它。 AIO 是创建大量执行同步 IO 的线程,或者在现在存在的 preadv 系列系统调用中使用分散/聚集的好选择。

可以使用新的 preadv 调用来执行“购物清单”同步 IO 作业,内核将从该调用中获取来自文件中不同偏移量的一堆页面。只要您只有一个文件要读取,就可以了。 (注意:存在等效的写入函数)。

poll、epoll 等只是执行 select() 的奇特方式,它们受到较少限制和可伸缩性问题的影响——它们可能无法轻松与磁盘 aio 混合,但在现实世界的应用程序中,您可能可以通过使用线程可以轻松解决这个问题(一些数据库服务器倾向于在单独的线程中执行这些类型的操作)。 poll() 很好,epoll 更好,对于大量的文件描述符。 select() 对于少量文件描述符(或者特别是少量文件描述符)也可以。

【讨论】:

  • (我认为 poll 和 select 是对称的并且 O(n),而 epoll 是 O(1)
  • poll 比 select 更好,因为它在使用一组稀疏的文件描述符时效果更好 - 假设您想从 10000 个打开的 FD 中轮询 10 个 FD,您不需要包含 10000 个条目的数组用零初始化。 epoll 更好,因为你只需要注册你感兴趣的新 FD,而不是把你已经在看的都传进去。
【解决方案3】:

(在 2019 年末,在最初的问题提出近十年后,一线希望出现了)

如果您有 5.1 或更高版本的 Linux 内核,您可以使用 io_uring interface,这有望为 Linux 带来更好的异步 I/O 未来(请参阅 Stack Overflow 问题的答案之一 "Is there really no asynchronous block I/O on Linux?" for @987654323 @)。希望这将使 Linux 能够与 FreeBSD 的异步 AIO without huge contortions 进行激烈竞争!

【讨论】:

    【解决方案4】:

    我学到的关于 Linux 中的异步 I/O 的大部分内容都是通过处理 Lighttpd 源代码获得的。它是一个单线程 Web 服务器,可以处理许多同时连接,使用它认为是运行系统上可用的任何异步 I/O 机制中最好的。查看源代码,它支持 Linux、BSD 和(我认为)其他一些操作系统。

    【讨论】:

      猜你喜欢
      • 2016-04-06
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 2021-07-22
      • 2010-10-10
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多