4

我是 Grand Central Dispatch 的忠实粉丝,最近我一直在看dispatch_io_*电话系列。很容易看出这个 API 如何对网络 I/O 有用(慢,高延迟)。也就是说,dispatch_io_create_with_path排序的存在意味着在本地文件系统上使用。(是的,我知道路径也可以指向远程网络文件系统上的资源,但无论如何......)在玩弄它时,我观察到dispatch_io_*与使用简单阻塞相比,使用似乎会带来相当大的开销I/O 调用 ( read,write, ETC。)。这种减速似乎主要来自用作块的内核同步原语在队列之间来回编组。在我一直在使用的示例工作负载中(非常受 I/O 限制),减速可能高达 10 倍。一方面,它看起来dispatch_io永远不会成为健谈(小颗粒)I/O 的胜利。

我假设在具有单个本地物理存储卷的单台机器的常见情况下,I/O 请求将在设备级别有效地序列化。从那里,我发现自己有这两个想法:

  • 如果您的工作负载受 CPU 限制,那么根据定义,您已经可以比处理数据更快地读取/写入数据。
  • 如果您的工作负载受 I/O 限制(在这种情况下 - 一个本地物理卷),则使用dispatch_io无法使您的磁盘更快地为您提供数据。

从那里开始,我认为这个 API 的最佳点可能在中间——一个在 CPU 密集型和 I/O 密集型之间摇摆不定的工作负载,但在这一点上,我有点认为自己陷入了困境,所以我想我会问 StackOverflow。

我将接受第一个描述具有这些先决条件(即单台机器、单个本地物理磁盘)的“真实世界”工作流的答案,使用这些前提条件dispatch_io会产生显着的性能改进。

4

1 回答 1

7

从本地文件系统调度 I/O 的主要用例是大文件的异步 IO,或同时读取/写入的许多文件(特别是如果文件的内容可以增量处理)。

来自本地文件系统的调度 I/O 针对延迟上的吞吐量进行了优化(例如,它在实际 IO 系统调用之前执行分块和咨询读取,以优化通过内核和驱动程序的 IO 路径上的流水线和吞吐量)。

鉴于 IO 系统调用在后台线程上异步执行,调度 IO 永远不会超过使用阻塞系统调用执行的小文件 IO 的延迟,特别是当没有其他 IO 活动正在进行时。

来自 WWDC11 的 GCD 会话详细介绍了调度 I/O,并通过示例比较了通过直接 read() 系统调用实现的吞吐量改进,以读取许多不同大小的文件。

于 2013-01-21T01:24:43.113 回答