为什么按名称删除文件既缓慢又异常快?


11

假步:我在下面提到的“快速”方法并不比慢速方法快60倍。它快了30倍。我将错误归咎于小时数(凌晨3点不是我思考的最佳时间:)。

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

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

所有测试均已处理了100万个文件。
(真实时间,用户时间和sys时间在测试脚本中)
可以在paste.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
#                                                       

我最近创建并删除了1000万个空测试文件。以名称为基础删除文件(即rm filename),我发现很难的方法是2种不同方法之间存在巨大的时差...

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

更新:事实证明,命令并不完全相同...其中一个命令一次向“ rm”发送1000个文件名...这是一个外壳括号扩展问题,我认为每个文件名都在写到供稿器文件的一行,但实际上每行是1000

filname是通过while read循环中的“ feeder文件”提供的。feeder
文件是的输出。ls -1 -f
方法在所有方面都是相同的,除了以下几点:

  • 缓慢的方法使用未排序的馈线文件直接ls -1 -f
  • 快速方法使用相同的未分类文件的排序版本

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

对于100万个文件,快速 rm filename方法比慢速方法快60倍……同样,我不知道这是“排序”问题还是幕后哈希表问题……我怀疑这不是一个简单的排序问题,因为为什么有意给我一个未排序的列表,其中列出了新添加的“排序”文件名序列... ls -1 -f

我只是想知道这里发生了什么,因此删除接下来的1000万个文件不需要花几天的时间(yes days):) ....我说“ days”是因为我尝试了很多选择,涉及的时间不成比例地增加到所涉及的文件数量..所以我只测试了100万个详细信息

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

...但是问题在这里“分类”了吗?还是与ext4使用的哈希(或其他)存储方法更相关?

令我感到困惑的是,每次呼叫rm filename都与上一个呼叫无关。(嗯,至少从“打击”角度来看是如此)

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


1
你这样做是错的!(tm)听说过find -delete吗?
alex

您的2个测试在不平等的条件下开始(我不认为这很重要):一个从文件中读取文件名,另一个从紧接在测试前创建(排序)的文件中读取文件名。可能是在第二种情况下缓存的文件播放了某些文件(或者不知道,谁知道)。为了使测试处于更平等的条件下,也许您应该cat在第一次测试之前对新文件进行简单的处理,而不是sort在第二次测试之前进行。
imz –伊万·扎哈拉里舍夫(Ivan Zakharyaschev)2011年

我建议您以更清晰的方式介绍您的观察和问题。请一次做一件事:在一个问题中仅比较两个案例,将这两个重要案例推到前台,其他都只是背景信息;请说清楚。请不要在一个帖子中混合几个观察结果。
imz-伊万·扎哈拉里谢夫(Ivan Zakharyaschev)2011年

提供您的系统时间和用户空间时间对于解决难题也可能很重要,因此请在您的问题中包括它们。哪一个对您的测试有重大影响?
imz –伊万·扎哈拉里舍夫(Ivan Zakharyaschev)2011年

1
过早的优化是万恶之源。:)什么时候删除1000万个文件?每秒10万对我来说似乎足够快(破坏您的系统)。
用户未知

Answers:


2

rm -r的递归预期会很慢。必须在目录结构上进行深度优先遍历。

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

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


1
McAlot:我看不到在这种情况下 “递归”有多重要,因为没有涉及子目录...是的,我确实使用了“ 1.txt,2.txt,3.txt”。也许有几个东西互动:比如,为什么它只需要1分30秒创造100万个文件,但它需要7米10秒,以创造200万个,并删除它们,再造100万之后,很多需要更长的时间(9米30秒)的怪异,一切运行慢慢地突然。这也发生过。我想(?)删除修复它的目录。可能有文件守护进程(nautilus; locate)吗?继续...
Peter.O 2011年

通常,文件系统并未针对在同一目录中处理大量文件进行优化。我对ext4并不特别熟悉,但是对于其他格式,删除文件时目录条目只是被标记为未使用。这意味着在目录中执行操作时仍必须跳过它们。那可以解释您所看到的行为。
KeithB 2011年

1
我删除了“现在变慢”的目录,并为新目录使用了不同的名称。创建100万个文件的时间现在回落到1m 33s(相比之下,目录“包含” 200万个已删除文件,而9m 30s则是9m 30s)……很有趣,而且附有您“ ...被标记为未使用”注释的注释...到达那里;它开始变得有意义了:)
Peter.O 2011年

@ fred.bear我不好,我真的不知道实际的层次结构,我的回答是猜测。您的测试实际上会强调元数据,而不是实际文件,因为它们是空文件。对此类问题进行基准测试的最佳方法是从/ var或Web服务器的缓存中获取文件。反正你也测试听起来intresting,你可以尝试用不同的directories..say像/sample1/1.txt,2.txt ......和/sample2/1.txt,2.txt两家上市方法删除..
rajaganesh87

@ Mr.Confused.A.Lot ...谢谢您的帮助。您的解释使我对文件系统及其某些行为方式有了更多的了解。...我现在对导致不同速度问题的原因有一个合理的认识...有些只是选择bash命令,而有些仅仅是文件系统问题(我留下一个新的座右铭:“大是坏的”目录...(至少要执行某些操作)...
Peter.O 2011年

2

您应该优化文件结构。所以代替

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

做一些更聪明的事情(假设重击):

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

当然,这都是从哈希表中随意借用的概念


我认为您是在说“使用较小的目录”。一个土生土长的DBMS,这使得一棵树从文件的“树少”群”。有些人可能会向前称之为计划:) ...如果它的工作原理(很可能如此),那么这是一个好主意!:) ...我开始有一个想法,“大是坏”,这涉及到目录中的文件数量(至少对于ext4)...您已经提出了先发制人的解决方法(+1),我m慢慢了解为什么在某些给定目录中某些删除方法比其他删除方法要快;无论大小,......
Peter.O 2011年

是的,您对保持
Dirs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.