虽然对于某些系统设计者来说,主内存被认为是相当便宜的,但并非总是可以将所有内容都存储在主内存中。当数据存储在外部存储器中时,人们必须仔细考虑如何访问数据。有几种存储设备和多个系统调用来从中读取数据。我们进行了实验,以找出不同的 Linux 系统调用对于可用设备的性能。总共通过单线程和多线程 pread、Linux aio 和新的 io_uring 接口访问了 HDD、SATA SSD、NVMe SSD 和 Intel Optane。完整报告以 PDF 格式提供: 链接。 我们给出了报告中的一个章节作为示例。
单次随机读取
外部存储设备是块设备,这意味着设备和主机之间的数据传输以块而不是单个字节完成。通常使用 512 字节或 4 千字节块。这些块大小是制造商很久以前选择的,可能不是现代设备的最佳选择。通过请求更大量的连续数据,我们可以模拟更大的块大小。让我们找出现代设备在较大块下的性能如何。
我们的目标是为随机读取选择最佳块大小。应用程序(或文件系统)可以选择任何块大小并根据此块大小访问数据。我们将块大小从 4 千字节到 32 兆字节不等。对于每个块大小,我们进行一些随机读取。在这些读取中,我们计算平均值、最小值和最大值延迟以及 99.0 和 99.9 百分位数。我们在本实验中使用系统调用 pread(2)。我们相信,lseek(2) 后跟 read(2) 应该具有相同的性能,因为观察到的存储访问时间远远长于系统调用。
硬盘驱动器
下图显示了 HDD 的结果。
对于小于 256 千字节的所有块大小,延迟几乎相同。发生这种情况是因为寻道时间远大于数据传输时间。寻道时间包括手臂定位以找到正确的磁道以及等待盘片旋转以将数据带到磁头下方。一个简单的结论是,对于 HDD 随机读取,应使用至少 256 千字节大小的块。即使应用程序使用较小的块,驱动器访问时间也相同。但是,人们仍然可以决定使用较小的块以获得更好的缓存利用率:如果每个请求的数据量很小并且预计适合缓存,那么存储一个大块以及请求的数据实际上会使缓存容量在有用数据方面变小。
256 千字节块读取平均需要 12 毫秒。我们经历了从 4 毫秒到 25 毫秒的变化。对于计算机来说,这确实是巨大的时间量。例如,典型的进程调度时间片只有几毫秒。当我们的进程等待数据从硬盘驱动器到达时,操作系统可以(并且实际上确实)执行其他进程。
SATA 固态硬盘
下图显示了 SATA 固态硬盘的读取延迟。
请注意,图中下部的时间单位是微秒(我们使用标准缩写 ms 表示毫秒,us 表示微秒)。读取 4 千字节大小的块平均需要 140 微秒,并且当块大小增加时,时间增长是线性的。与 HDD 相比,从 SSD 读取 4 千字节块的速度快 80 倍。对于 256 千字节块,SSD 比 HDD 快十倍。当块大小足够大(从 4 兆字节开始)时,SSD 仅比 HDD 快两倍。
NVMe 固态硬盘
下图显示了 NVMe 固态硬盘的结果。
延迟优于 SATA 固态硬盘。对于 4 千字节块大小,平均时间仅略有改善,但 99 百分位数降低了两倍。从 NVMe 固态硬盘读取 1 兆字节块不到 1 毫秒。对于 SATA 固态硬盘,这需要 3 毫秒。正如我们所见,从 SATA 固态硬盘升级到 NVMe 固态硬盘不如从 HDD 升级到 SATA 固态硬盘那样显着。这并不奇怪,因为 SATA 和 NVMe 固态硬盘都基于相同的技术。只有接口不同。
Intel Optane
下图显示了 Intel Optane 固态硬盘的结果。
最小延迟为 12 微秒,比 NVMe 固态硬盘低 10 倍。平均延迟比 HDD 低 1000 倍。小块读取延迟的变化相当大:即使平均时间非常低并且接近最小延迟,最大延迟甚至 99 百分位数也明显更差。如果有人查看这些结果并希望创建一个基于 Intel Optane 的服务,读取延迟为 12 微秒,他们将不得不安装更多数量的 Intel Optane 驱动器,或者考虑提供更实际的计时。
当延迟如此小时,上下文切换和中断处理的开销变得显着。可以使用轮询模式来获得一些改进。在这种模式下,Linux 内核监视完成队列,而不是切换到其他作业并依赖硬件中断和中断处理程序来通知完成。显然,只有当预计硬件响应足够快到达时,才值得使用轮询模式。
上图显示了在轮询模式下从 Intel Optane 读取的结果。当应用程序使用 RWF_HIGHPRI 标志调用 preadv2(2) 系统调用时,将使用轮询模式。与通常的 pread(2) 相比,轮询模式将最大延迟降低了二倍,对于高达 256 千字节的块大小。
总结
为了总结我们的结果,下图显示了所有四种存储类型的单次读取延迟在单个图表上。
从 4 兆字节开始,延迟很容易通过线性外推法预测,因此我们不在此处显示更大的块。为了在单个图中显示所有内容,我们不得不使用相当过载的图例。我们使用垂直级别来显示延迟,并在水平方向上迭代块大小。对于每个块大小,我们显示四个条形,从左到右:用于 Intel Optane、NVMe 固态硬盘、SATA 固态硬盘和 HDD。存储类型由阴影线表示,延迟由颜色表示。
我们看到固态设备延迟远优于 HDD。对于单次读取,领先者是 Intel Optane,但正如我们稍后将看到的,与 NVMe 固态硬盘相比,它有自己的缺点。当块大小较小时,NVMe 固态硬盘和 SATA 固态硬盘看起来非常接近。我们的观察表明,随机读取的最佳块大小对于 HDD 是 256 千字节,对于 NVMe 和 SATA 固态硬盘是 4 千字节,对于 Intel Optane 是 8 千字节。
那么,测试 Linux 中的现代 IO 接口怎么样?继续阅读完整文章。
2021-03-09 Ruslan Savchenko