如何估算文件系统中的查找速度

假设在1TB SSD上有一个大文件(以500MB /秒的速度读写)和ext4文件系统。 这个文件大小接近1TB。 如何估计fseek()到文件中间的速度。 是要花几秒还是几毫秒? 谢谢。

为了估计fseek延迟,我们应该把它分成两部分:软件工作和硬件寻道时间延迟。 软件工作是ext4文件系统(FS,在Linux中是内核的VFS子系统)的实现,它会对硬件块存储设备产生几个“随机”请求(I / O操作)。 硬件将使用一些时间来处理每个随机请求。

经典UNIX文件系统(UFS / FFS)和linux文件系统,在它们之后设计,使用超级块来描述磁盘上的磁盘,将文件存储为索引节点(在已知位置有inode数组),并以固定大小的块存储文件数据(在Linux中高达4KB)。 从文件名OS查找索引节点必须读取超级块,查找路径中的每个目录,从目录读取数据以查找文件的索引节点号( ls -i将显示当前目录的索引节点)。 然后,使用来自超级块OS的数据可以计算inode存储和读取inode的位置。

Inode包含文件数据块的列表,通常以树状结构,请查看https://en.wikipedia.org/wiki/Inode_pointer_structure或http://e2fsprogs.sourceforge.net/ext2intro.html ext2 inode指针结构,来自e2fsprogs.sourceforge.net/ext2intro.html的gpl

文件的第一部分,几十KB存储在块中,直接列在索引节点(直接块; ext2 / 3/4中的12)。 对于较大的文件,inode具有指向具有文件块列表(间接寻址的块)的一个块的指针。 如果文件较大,则使用inode中的下一个指针来描述“双重间接块”。 它指向枚举其他块的块,每个块都包含指向具有实际数据块的指针。 有时需要三重间接块指针。 这些树是相当有效的,在每个级别有〜512(4KB块,每个指针8字节)的程度。 所以,为了从文件中间访问数据,ext2 / 3/4最多可以产生4-5个低级I / O请求(超级块被缓存在RAM中,inode也可以被缓存)。 这些请求在地址中不是相应的,所以它们几乎是对块设备的随机寻找。

linux FS(ext4,XFS)的现代变体已经对称为extent的大文件存储进行了优化( https://en.wikipedia.org/wiki/Extent_(file_systems) )。 范围允许FS描述文件放置不是作为块列表,而是作为文件片段/指针对(start_block,number_of_consequent_blocks)的数组。 每个片段可能是从MB的一部分到128 MB。 4个第一范围存储在inode中,更多的范围再次存储为树状结构。 因此,使用扩展可能需要2-4个随机I / O操作来访问文件的中间。

硬盘驱动器对随机请求的访问时间很慢,因为它们应该在物理上移动标题来纠正循环轨迹(并且正好在轨道上定位标题;这需要旋转一些部分,比如1/8或1/16),然后等待用于多达1转(盘旋)的磁盘(盘片)以获得要求的部分轨道。 硬盘的典型转速为5400和7200转( 每分钟转数 ,90 转和120转)或高速企业级硬盘 – 10000转和15000转(160转和250转)。 所以,从盘的随机位置获取数据所需的平均时间大约是0.7-1圈,对于典型的7200转/ hdd(120rps),大约是1/120秒= 8毫秒(毫秒)= 0.008秒。 需要8ms来获取每个随机请求的数据,并且在您的情况下有多达4-5个随机请求,所以对于HDD,您可能预计时间高达40毫秒左右来查找文件。 (第一次搜索将花费更多,接下来的寻找可能会更便宜,因为块指针树的某些部分被操作系统缓存;寻找几个下一个块是非常便宜的,因为Linux只要求第一次搜索就可以读取它们)。

SSD没有旋转或移动的部分,SSD上的任何请求都以相同的方式处理。 SSD控制器使用自己的转换表将请求的块ID解析到内部nand芯片+块ID,然后读取真实数据。 从NAND读取数据将检查纠错码,有时需要几次内部重读来正确读取块。 低成本的NAND型读取速度较慢 – 每个单元存储3位数据的TLC – 8级; MLC中速度更快 – 4个级别的2位数据; 在不存在SLC SSD的情况下,速度非常快,只有1位,只有2个级别。 在磨损的固态硬盘或SSD固件中出现错误(电池电量降低的错误模型)时,读取速度也会变慢。

SSD中这种随机访问的速度非常高,通常宣称SSD规格为50000 – 100000 IOPS( 每秒I / O操作 ,通常为4KB)。 对于更深的队列,可能会宣布高IOPS计数,所以SSD(带QD1)的实际平均随机读取延迟为每个请求200-300微秒 (0.2 – 0.3 ms; 2014年;部分延迟是SATA / SCSI仿真速度较慢; NVMe固态硬盘可能会更快,因为他们使用更简单的软件堆栈)。 根据我们的4-5个请求,我们可以估计SSD上的 fseek为几毫秒,例如高达1 – 1.5毫秒 ,有时甚至更长。

您可以使用strace -T ./your_fseek_program来检查fseek所需的时间。 它会报告执行每个系统调用所需的时间。 但是为了得到真正的延迟,你不仅要检查时间,还要检查下一次系统调用的时间。 在每次运行此测试之前,您可能需要使用echo 3 > /proc/sys/vm/drop_caches命令从根目录刷新内核缓存( https://unix.stackexchange.com/questions/17936/setting-proc-sys-vm -drop-caching-to-clear-cache )。

您也可以尝试一些I / O基准,如iozone,iometer或fio来估计搜索延迟。