文件组织对文件访问效率的影响

文件组织对文件访问效率的影响

目录结构中文件的组织可以显着影响文件访问的效率(参考)。举例来说,考虑两个目录AB,每个目录包含 10^6 个文件,在前一种情况下组织在一个目录中,在后一种情况下组织在 10^3 个子目录中。在前一种情况下,计算或列出所有文件的速度明显较慢。在我的系统上:

创建文件:

$ mkdir A; pushd A; seq -w 1E6 | xargs touch; popd
$ mkdir B; pushd B; seq -w 1E3 | xargs mkdir; for d in *; do pushd "$d"; seq -w 1E3 | xargs touch; popd; done; popd

列出文件:

$ for d in A B; do
    time for i in {1..100}; do
        {
            echo 3 | sudo tee /proc/sys/vm/drop_caches
            find "$d" -type f
        }
    done >/dev/null
done

# case A (0 subdirectories)
real    4m49.805s
user    1m43.696s
sys     1m13.540s

# case B (1000 subdirectories)
real    3m32.338s
user    0m40.824s
sys     1m13.176s

该差异是可重现的,独立于磁盘缓存,并且不特定于命令find(即,使用 找到相同大小的差异ls -RU)。在这两种情况下,内核空间中的时间量是相同的,从而免除了内核(以及可能的文件系统机制)的责任。虽然我没有进行任何分析,但几乎可以肯定进行的主要系统调用,readdir()并且getdents()由于两种情况下 inode 的数量相同(在 0.1% 以内),文件的大小、所需的时间也相同因为内核执行这些调用不会有什么不同。因此,执行时间的差异可归因于用户空间代码。

一些 GNU coreutils 中添加了线程支持(例如sort)。由于我的系统有四个硬件线程,并且我不确定 GNU find(我的系统版本是 4.7.0-git)是否具有多线程功能,因此我验证了与显式绑定到单个硬件线程的进程之间的差异是否存在:

$ cat find.sh
#!/bin/bash
for i in {1..100}; do
  {
    echo 3 | sudo tee /proc/sys/vm/drop_caches
    find "$1" -type f
  }
done >/dev/null

$ for d in A B; do time taskset -c 0 ./find.sh "$d"; done

# case A (0 subdirectories)
real    4m7.827s
user    1m31.080s
sys     0m55.660s

# case B (1000 subdirectories)
real    2m53.059s
user    0m33.256s
sys     0m52.772s

因此,我最初的问题可以细化如下:纯粹由于文件系统组织差异而导致访问时间差异的用户空间效率低下的原因是什么?了解这些低效率应该可以更好地实现文件访问例程。

编辑:ext4我正在运行 linux 内核的机器上 使用文件系统4.9.0-4-amd64,尽管我有兴趣知道答案在多大程度上取决于所选的文件系统。

答案1

没有太多证据,我猜测 find 最终会调用 realloc 并多次复制目录数据,因为它在单目录情况下的初始分配中运行空间。但在多目录情况下,支持每个子目录读取的内存不需要那么多副本或重新分配。您可以检查 find 的总体内存使用情况(以某种方式?)来验证。

相关内容