在早期的帖子中,我展示了如何并行访问Data Onan SSD可以大大提高读取性能。但是,该技术对于存储在纺纱驱动器上的数据并不非常有效。在某些情况下,并行AccessCan甚至显着降低了性能。幸运的是,存在一类优化可以强烈帮助HDD:请求订购。通过按照正确的顺序请求数据,磁盘寻求延迟可以减少一个级别。由于我介绍了FCLONES 0.9中的优化,因此FCLONES成为我所知道的最快的重复文件查找器。
与SSD相反的纺纱驱动器具有重要的访问延迟,限制了每秒IO操作的影响,他们可以服务。磁盘访问延迟主要由以下组成:
旋转延迟 - 等待磁盘旋转所需的时间,以便正确的扇区位于头部下方,
寻求延迟更高,距离移动到右轨道的距离越多。制造商广告的典型平均搜索延迟大约是5-12毫秒。平均旋转延迟等于磁盘板的一半匝数所需的时间。在7200rpm驱动器的情况下,这等于60/7200/2 = 4.2 ms。总的来说,总平均延迟可以是大约10毫秒,最坏情况延迟超过20毫秒。
现在,如果我们想处理一堆在磁盘上随机放置的微小文件,我们将在随机顺序中访问它们,我们不应该预计每秒大约100多个(你可能会幸运,那么你的一些文件彼此靠近,可以改善它)。
这个背面的信封计算在现实世界中持续得很好。以下是一个示例iostat输出,同时搜索具有旧版本的fclones(0.8)的Duplicateson A 7200 RPM HDD:
设备TPS KB_READ / S KB_WRTN / S KB_READ KB_WRTNSDA 127,40 655,20 0,00 3276 0SDB 0,60 0,00 67,20 0 336DEVICE TPS KB_READ / S KB_WRTN / S KB_READ KB_WRTNSDA 135,00 659,20 0,00 3296 0SDB 26,00 0,00 174,40 0 872DEVICE TPS KB_READ / S KB_WRTN / S KB_READ KB_WRTNSDA 132,60 669,60 0,00 3348 0SDB 0,40 0,00 8,00 0 40DEVICE TPS KB_READ / S KB_WRTN / S KB_READ KB_WRTNSDA 127,40 683,20 0,00 3416 0SDB 0,40 2,40 28,00 12 140
我们可以看到每秒交易数量略高于100.这是考虑到SSD可以处理数十甚至每秒数百个随机访问的易易幂。数据速率也基本上通过延迟“杀死”。此驱动器可以连续读取100多MB / s,但在这里我们获得数百千字节的速率。
遗憾的是,即使在2021年,您仍然可能在较旧的HDD上呈现出大量千兆字节。如果您想处理所有这些(例如,搜索,备份或重复申请),那么你是否注定要等待几小时?
在[1]中,作者通过对操作系统进行分类,介绍了一种提高性能的一些好技术,以便执行。我在FCLONES中实施了它们,结果令人惊叹!
最多为0.8版,FCLONES按照其尺寸的顺序处理文件,因为这是从分组的第一阶段获得的orthnaturally。正如您所希望的那样,事实证明,文件大小根本没有与文件的物理位置相关联。因此,HDD上的性能实际上比在从扫描目录树中获得的顺序处理文件。至少,当在目录列表返回的顺序中处理文件时,它们在类似的时间内保存了很高的机会(例如,作为目录复制操作的结果),并且实际上彼此非常接近。事实上,尽管没有真正做出任何特殊速度磁盘访问,但某些替代程序就像FDUPES或RDFind一样表现优于硬盘上的FCLONES。
我尝试的第一个想法之一是通过inode标识来重新排序文件。这很容易,因为inode标识符已经在文件元数据结构中可用,以便正确检测链接。老实说,我并没有期待这种技术的改善,在理论上,文件姓氏的inode数与物理数据位置无关。在实践中,似乎有很多相关性。尽管一些小型增加了分类的成本,但这种技术就像魅力一样。
我们可以做得更好。一些文件系统,如Linux ext4,提供了一个用于获取有关文件扩展名信息的API:Fiemap Ioctl.we可以使用此API获取包含有关文件数据物理放置信息的数据结构。然后,可以使用数据开始的物理放置来对文件进行排序,以便我们可以在单个扫描中处理文件。一个好消息是,这个API也可用于非root用户。
使用Fiemap在Rust中很容易,因为已经有一个铁锈箱为此:Fiemap。 FCLONES代码的相关片段如下所示:
#[cfg(target_os =" linux")pub fn get_physical_file_location(路径:&路径) - > IO ::结果<选择< U64>> {让mut extents = fiemap :: fiemap(& path .to_path_buf())? ;匹配extents .next(){一些(fe)=>好的(一些(fe?.fe_physical)),none =>好的(无),}}
我最初担心每个文件的额外系统调用都会增加一些初始成本,取消了访问排序的Gains。幸运的是,它证明了成本真的很低 - 50k文件可以在不少于秒的时间内找到范围!我猜这一个事实已经在早期阶段查询了文件的元数据,因此所有的信息都已在缓存中。图2显示了尽管系统呼叫数量越多,但任务的总时间甚至减少到大约19秒!这比早期发布速度超过10倍。
ioStat报告的每秒交易数量和吞吐量也相当于上升。现在在单个磁盘板转动中读取Many文件。
设备TPS KB_READ / S KB_WRTN / S KB_READ KB_WRTNSDA 2424,40 11605,60 0,00 58028 0SDB 1,00 4,80 11,20 24 56DEVICE TPS KB_READ / S KB_WRTN / S KB_READ KB_WRTNSDA 2388,20 10436,80 0,00 52184 0SDB 6,60 356,80 38,40 1784 192Device TPS KB_READ / S KB_WRTN / S KB_READ KB_WRTNSDA 2397,00 11188,00 0,00 55940 0SDB 3,20 80,80 56,80 404 284
在介绍重新排序之前,我发现并行发出的请求,以便读取小(4-64 kB)数据的数据提高速度。操作系统肯定会充分利用提前了解某些文件并自行重新排序访问。我们订购读数后仍然是这种情况吗?也许给操作系统提前一点请求仍然可以节省一些时间?我认为该系统可以在技术上工作,而在应用程序仍在处理之前的应用程序时,请执行获取下一个文件。
不幸的是,至少在我的系统上,这似乎不起作用。在并行降级的性能中获取文件一位(图3)。该效果与大文件的顺序访问没有巨大,但足够大,我在FCLONES中更改了0.9.1中的默认值,现在使用每HDD设备单线。
文件I / O请求的顺序对旋转驱动器上的I / O性能产生了巨大影响。如果您的应用程序需要处理一批小文件,请确保以与磁盘上的物理放置相同的顺序请求它们。如果您不能这样做,因为您的文件系统您的操作系统不提供物理块放置信息,请至少由其标识符进行文件。如果您幸运的话,标识符将与数据的物理放置高度相关,并且这种订单仍然会做一些魔法。
如果您尝试过此帖以及您有多大的改进,请在评论中告诉我。 [1] C. Lunde,H.Espeland,H. Stensland和P. Halvorsen,“通过安排用户空间中的I / O操作来改善文件树遍历性能,”2009年12月,第145-152页,DOI:10.1109 /pccc.2009.5403829。