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