Seb*_*ian 28 ls performance filesystems time
我在一个目录中有几个文件:
$ ls | wc -l
9376
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释为什么使用ls *and有这么大的时差ls?
$ time ls > /dev/null
real 0m0.118s
user 0m0.106s
sys 0m0.011s
Run Code Online (Sandbox Code Playgroud)
和
$ time ls * > /dev/null
real 1m32.602s
user 0m0.233s
sys 0m0.438s
Run Code Online (Sandbox Code Playgroud)
好吧,这是一个极端的例子,可能会有所增强,因为该目录位于通用并行文件系统 (GPFS) 上。但我也可以看到本地文件系统的显着放缓。
编辑:
$ time ls -l > /dev/null
real 0m58.772s
user 0m0.113s
sys 0m0.452s
$ time ls -l * > /dev/null
real 1m19.538s
user 0m0.252s
sys 0m0.461s
Run Code Online (Sandbox Code Playgroud)
我应该补充一点,在我的例子中没有子目录:
$ diff <(ls) <(ls *)
$
Run Code Online (Sandbox Code Playgroud)
cam*_*amh 47
当你ls不带参数运行时,它只会打开一个目录,读取所有内容,对它们进行排序并打印出来。
当您运行时ls *,首先 shell 展开*,这实际上与 simplels所做的相同,使用当前目录中的所有文件构建一个参数向量并调用ls. ls然后必须处理该参数向量和每个参数,并调用access(2)¹ 文件以检查它的存在。然后它将打印出与第一个 (simple) 相同的输出ls。shell 对大参数向量和ls's的处理都可能涉及小块的大量内存分配,这可能需要一些时间。然而,由于很少有sys和user时间,但很多real时候,大部分时间会花在等待磁盘,而不是使用CPU做内存分配。
每次调用access(2)都需要读取文件的 inode 以获取权限信息。这意味着比简单地读取目录要多得多的磁盘读取和搜索。我不知道这些操作在您的 GPFS 上的开销有多大,但正如您所展示ls -l的与通配符情况下运行时间相似的比较,检索 inode 信息所需的时间似乎占主导地位。如果 GPFS 在每次读取操作上的延迟比您的本地文件系统稍高,我们预计在这些情况下它会更明显。
通配符大小写和ls -l50%之间的差异可以通过磁盘上 inode 的顺序来解释。如果 inode 以与目录中的文件名相同的顺序连续ls -l排列,ls -l并在排序之前按目录顺序对文件进行 stat(2)ed,则可能会在一次扫描中读取大部分 inode。使用通配符,shell 将在将文件名传递给之前对文件名进行排序ls,因此ls可能会以不同的顺序读取 inode,从而增加更多的磁盘磁头移动。
应该注意的是,您的time输出将不包括 shell 扩展通配符所花费的时间。
如果你真的想看看发生了什么,请使用strace(1):
strace -o /tmp/ls-star.trace ls *
strace -o /tmp/ls-l-star.trace ls -l *
Run Code Online (Sandbox Code Playgroud)
并查看在每种情况下正在执行哪些系统调用。
¹我不知道是否access(2)实际使用过,或其他诸如stat(2). 但两者都可能需要 inode 查找(我不确定是否access(file, 0)会绕过 inode 查找。)
| 归档时间: |
|
| 查看次数: |
3366 次 |
| 最近记录: |