Unix目录inode - 碎片和转储目录内容

时间:2009-10-27 00:13:12

标签: linux

我们在Linux上遇到问题,目录inode变得越来越大,随着时间的推移很慢,因为创建和删除了许多文件。例如:

% ls -ld foo
drwxr-xr-x    2 webuser  webuser   1562624 Oct 26 18:25 foo
% time find foo -type f | wc -l
    518
real    0m1.777s
user    0m0.000s
sys     0m0.010s

% cp -R foo foo.tmp
% ls -ld foo.tmp                                                                       
drwxr-xr-x    2 webuser  webuser     45056 Oct 26 18:25 foo.tmp   
% time find foo.tmp -type f | wc -l
    518
real    0m0.198s
user    0m0.000s
sys     0m0.010s

原始目录有518个文件,需要1.5 MB来表示,并且需要1.7秒才能遍历。

重建目录具有相同数量的文件,需要45K表示和.2秒才能遍历。

我想知道是什么原因引起的。我的猜测是碎片 - 一般来说这不应该是Unix文件系统的问题,但是在这种情况下我们使用该目录用于短期缓存文件,因此不断创建,重命名和删除大量小文件

我也想知道是否有办法转储目录的文字二进制内容 - 也就是说,读取目录就好像它是一个文件 - 这可能会让我深入了解为什么它如此之大。 Perl的read()和sysread()都不允许我:

 swartz> perl -Mautodie -MPOSIX -e 'sysopen(my $fh, "foo", O_RDONLY); my $len = sysread($fh, $buf, 1024);'
 Can't sysread($fh, '', '1024'): Is a directory at -e line 1

系统信息:

Linux 2.6.18-128.el5PAE #1 SMP Wed Dec 17 12:02:33 EST 2008 i686 i686 i386 GNU/Linux

谢谢!

乔恩

2 个答案:

答案 0 :(得分:2)

对于问题1,外部碎片通常会导致大约2倍左右的开销, 1 以及分配粒度的内部碎片。这些都不能解释你的观察结果。

所以,我不认为这是正常的稳态碎片。

最明显的猜测是1.5MB是高水位;有一段时间它确实有1.5MB字节的条目或1.5MB / 2字节的条目与预期的碎片。

另一种猜测是50%的规则被非马尔可夫分配击败。想象一下,我用“tmp%d”命名文件,因此,tmp1,tmp2,... tmp1000,tmp1001,......

这里的问题是rm tmp1没有为tmp1001腾出空间。这显然是一个疯狂的猜测。

Q2:没有一种好方法可以读取原始目录。 AFAIK,您需要破解内核或使用debugfs更改inode类型,读取它,然后将其更改回来,或使用debugfs读取inode,获取块编号,然后读取块。功能调试方法可能更合理。

您可以通过确保启用索引来解决性能问题。请参阅tune2fs


1 Knuth的百分之五十的规则:在稳定状态下,50%的操作是分配,50%是自由,50%的空闲块合并,然后漏洞是50%的分配,50空间的百分比被浪费了。 (Aka,100%开销。)这被认为是“正常的”。 Malloc也有同样的问题。

答案 1 :(得分:0)

这是因为重复文件创建和删除造成的碎片。随着inode大小的增加,它永远不会再缩小,所以即使大部分都是空的,它也会保持很大。

我认为你主要有两种措施来解决这个问题:

  1. 构建子目录结构,以防止在单个目录parent下有太多子项。例如,如果要创建路径格式为dir/file-%06d的文件,那么您将使其拥有一百万个具有预期的巨大目录inode的子项。您宁愿设计一些子树结构,将文件名分解为其变量前缀,例如,如果您的文件是file-123456.ext,则在dir/files/1/2/3/4/123456.ext之类的内容下分配它们。此策略将最终目录叶下的最大子项数限制为1000。分解的级别取决于文件名的可变部分的大小。

  2. 作为对策,一旦你已经拥有庞大的目录inode,除了创建一个新的(小节点)兄弟目录,将所有原始(。)文件移动到新目录之外别无其他,删除原始目录并将新目录重命名为原始名称。注意在原始路径下同时运行服务。

  3. 在目录中涉及findstat --printf='%b'%s的一些shell-fu可以帮助您检测文件系统中的其他麻烦点,并将它们置于密切观察之中。

    有关特定文件系统的详细信息,请look at this post in ServerFault.com