为什么按名称删除文件速度慢得令人痛苦,但速度却异常快?

为什么按名称删除文件速度慢得令人痛苦,但速度却异常快?

失礼之处:我下面提到的“快速”方法并不比慢速方法快 60 倍。速度快了 30 倍。我会把这个错误归咎于时间(凌晨 3 点不是我一天中清晰思考的最佳时间:)..

更新:我添加了测试时间摘要(如下)。
速度因素似乎涉及两个问题:

  • 使用命令的选择(时间比较如下所示)
  • 目录中存在大量文件的本质...似乎“大就是坏”。随着数量的增加,事情变得不成比例地变慢。

所有测试均使用 100 万个文件完成。
(真实时间、用户时间和系统时间位于测试脚本中)
测试脚本可以在以下位置找到:粘贴.ubuntu.com

#
# 1 million files           
# ===============
#
#  |time   |new dir   |Files added in  ASCENDING order  
#  +----   +-------   +------------------------------------------------- 
#   real    01m 33s    Add files only (ASCENDING order) ...just for ref.
#   real    02m 04s    Add files, and make 'rm' source (ASCENDING order) 
#                      Add files, and make 'rm' source (DESCENDING order) 
#   real    00m 01s    Count of filenames
#   real    00m 01s    List of filenames, one per line
#   ----    -------    ------
#   real    01m 34s    'rm -rf dir'
#   real    01m 33s    'rm filename' via rm1000filesPerCall   (1000 files per 'rm' call)
#   real    01m 40s    'rm filename' via  ASCENDING algorithm (1000 files per 'rm' call)
#   real    01m 46s    'rm filename' via DESCENDING algorithm (1000 files per 'rm' call)
#   real    21m 14s    'rm -r dir'
#   real    21m 27s    'find  dir -name "hello*" -print0 | xargs -0 -n 1000 rm'
#   real    21m 56s    'find  dir -name "hello*" -delete'
#   real    23m 09s    'find  dir -name "hello*" -print0 | xargs -0 -P 0 rm'
#   real    39m 44s    'rm filename' (one file per rm call) ASCENDING
#   real    47m 26s    'rm filename' (one file per rm call) UNSORTED
#                                                       

我最近创建并删除了10万个空测试文件。按名称删除文件(即rm filename),我艰难地发现有一个巨大的两种不同方法之间的时间差...

两种方法都使用完全相同的rm filename命令。

更新:事实证明,这些命令并不完全相同...其中一个是一次向“rm”发送 1000 个文件名...这是一个 shell 大括号扩展问题,我认为每个文件名都被写入到 feeder 文件单独一行,但实际上每行 1000 个

文件名是通过“馈送文件”提供到while read循环中的。
馈送文件是 的输出ls -1 -f
这些方法在所有方面都是相同的,除了一件事:

  • 慢的方法直接使用未排序的 feeder 文件ls -1 -f
  • 快速地方法使用同一未排序文件的排序版本

我不确定排序是否是这里的问题,或者排序后的馈送文件是否恰好与创建文件的顺序匹配(我使用了简单的升序整数算法)

对于 100 万个文件,快速地 rm filename方法是60慢的方法...再说一次,我不知道这是一个“排序”问题,还是幕后哈希表问题...我怀疑这不是一个简单的排序问题,因为为什么会ls -1 -f故意给我一个取消排序新添加的“排序”文件名序列的列表...

我只是想知道这里发生了什么,所以不需要我几天(是的几天)来删除接下来的 1000 万个文件:) ....我说“天”是因为我尝试了很多替代方案,并且涉及的时间与涉及的文件数量不成比例地增加..所以我只测试过1万详细

顺便说一句:通过名称的“排序列表”删除文件实际上比“排序列表”方法快rm -rf2 倍。
并且:rm -r比“排序列表”方法慢 30 倍

...但是这里的问题“排序”了吗?或者它与 ext4 使用的散列(或其他)存储方法更相关?

让我很困惑的是,每次调用rm filename都与前一个无关..(好吧,至少从“bash”的角度来看是这样)

我正在使用 Ubuntu / bash / 'ext4' / SATA II 驱动器。

答案1

rm -r 预计会因为递归而变慢。必须对目录结构进行深度优先遍历。

那么你是如何创建 1000 万个文件的呢?你是否使用了一些按某种顺序循环的脚本? 1.txt,2.txt,3.txt...如果是,那么这些文件也可能以相同的顺序分配在 hdd 中的连续块中。因此按相同的顺序删除会更快。

“ls -f”将启用 -aU,它按目录顺序列出,这又是递归的。

答案2

您应该优化文件结构。所以而不是

for i in $(seq 1 1000); do touch file.$i; done

做一些更聪明的事情,比如(bash 假设):

function bucklocate() 
{ 
    hash=$(echo -n "$1"|md5sum|cut -f1); 
    echo -n "${hash:1:1}/${hash:7:1}/${hash:9:2}/$1"; 
}

hexdig="{0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}"
eval mkdir -p $hexdig/$hexdig/$hexdig$hexdig


for i in $(seq 1 1000); do touch $(bucklocate file.$i); done

现在这个例子相当慢,因为使用了 md5sum[1],使用类似下面的东西可以更快地响应,只要你不需要任何特定的文件名,重复就不用担心,也不需要某个名称的可重复哈希:)

mkdir -pv {0,1,2,3,4,5,6}/{0,1,2,3,4,5,6,7,8,9,10,12}
for  a in $(seq 1 100); do i=$RANDOM; echo touch "$(($i%7))/$(($i%13))/file.$i"; done

当然,这都是草率地借用哈希表的概念

相关内容