Linux/ext4 下的 NVMe SSD 是否会出现非常偶然、非常高的读取延迟?

Linux/ext4 下的 NVMe SSD 是否会出现非常偶然、非常高的读取延迟?

背景环境信息:我正在开发一个从 NVMe SSD 流式传输多个音轨的应用程序,并且正在测量系统的性能以确定我需要提供多少缓冲,以避免由于不同的磁盘读取而导致任何音频欠载。

为简单起见,我运行的是一台闲置、无 GUI、真实硬件的 20 核 Linux 服务器,文件系统为 ext4,我将程序设置为仅通过单个线程读取音频数据(在实际使用中,它将使用多个 I/O 线程,但我看到的 SSD 行为类似)。我将其设置为同时从 1,536 个 96kHz 音频文件中读取数据,因此预期的数据吞吐量为(3*96000*1536) = ~421 MB/sec,平均而言,SSD 和 CPU 可以很好地处理。在我的测试工具中,音频数据在读取后被丢弃。

但是,我的问题是关于读取延迟的。特别是,我注意到 99.99% 的读取请求(每个请求 128KB)在不到 1 毫秒的时间内得到处理,这很棒。但是,极少数读取需要更长时间(大约几毫秒),偶尔我会遇到一个非常可怕的异常值,可能需要长达 200 毫秒(!)才能完成。

我对我的程序进行了调试,建立了一个测量读取延迟的直方图,并在几个小时内报告了以下情况:

Read latencies histogram:
  41358428 @ <1mS
      1328 @ 1-9 mS 
       440 @ 10-19 mS
       432 @ 20-29 mS
        33 @ 30-39 mS 
       109 @ 40-49 mS
        43 @ 50-59 mS 
        10 @ 60-69 mS 
         5 @ 70-79 mS  
         2 @ 80-89 mS  
         4 @ 90-99 mS  
         2 @ 100-109 mS
         5 @ 130-139 mS
         1 @ 140-149 mS
         3 @ 150-159 mS
         1 @ 170-179 mS
         2 @ 180-189 mS
         4 @ 190-199 mS
         1 @ 200-209 mS

我的问题是,这种“长尾”行为是否是现代 NVMe SSD 驱动器的预期行为,还是非常罕见的 100+mS 延迟的存在是否表明我的硬件或软件存在问题?我不知道我是否应该接受这个现实,增加应用程序的缓冲区大小,然后继续前进,或者我是否应该尝试找出导致长读取的原因并修复它。

根据评论更新:SSD 的型号是TS2TMTE662T2-G1,我认为这意味着它是这些

输出自lsblk,供参考:

root@xxxxx:~# lsblk -o NAME,FSTYPE,LABEL,MOUNTPOINT,SIZE,MODEL
NAME         FSTYPE      LABEL MOUNTPOINT  SIZE MODEL
nvme0n1                                    1.9T TS2TMTE662T2-G1                         
|-nvme0n1p1  vfat                          512M 
|-nvme0n1p2  crypto_LUKS                     8G 
| `-rootfs_a ext4                            8G 
|-nvme0n1p3  crypto_LUKS                     8G 
| `-rootfs_b ext4              /             8G 
|-nvme0n1p4  ext4              /var/log      2G 
|-nvme0n1p5  ext4              /cfg        128M 
`-nvme0n1p6  ext4              /udata      1.8T 

答案1

通过进一步探索和测试,我发现间歇性高延迟的一个常见原因是 SSD 驱动器的垃圾收集。

具体来说,由于 NAND 闪存的工作方式,每当 SSD 固件想要写入更多数据时,它都需要一个新的(全零)闪存页面来写入数据。如果它还没有可用的闪存页面,它必须在闪存块上执行一个相当耗时的“擦除”步骤来创建一个,然后 I/O 请求才能完成。这种行为可能会导致非常高的延迟,但可以通过运行以下命令来(大部分)避免弗斯特里姆在驱动器上定期进行此操作(以便驱动器在使用时不会用尽全零页面)。

请注意,这种行为仅在驱动器被写入和读取时才会显现,并且可能还有其他原因导致偶尔出现高延迟,但我还不知道。

相关内容