Bah*_*ram 7 linux performance permissions find files
在我的 CentOS 7.6 上,我通过运行创建了一个包含 3,000,000 个文件的文件夹(称为 many_files):
for i in {1..3000000}; do echo $i>$i; done;
Run Code Online (Sandbox Code Playgroud)
我正在使用该命令find
将有关此目录中文件的信息写入文件。这工作得非常快:
$ time find many_files -printf '%i %y %p\n'>info_file
real 0m6.970s
user 0m3.812s
sys 0m0.904s
Run Code Online (Sandbox Code Playgroud)
现在,如果我添加%M
以获取权限:
$ time find many_files -printf '%i %y %M %p\n'>info_file
real 2m30.677s
user 0m5.148s
sys 0m37.338s
Run Code Online (Sandbox Code Playgroud)
该命令需要更长的时间。这对我来说非常令人惊讶,因为在 C 程序中我们可以使用它struct stat
来获取文件的 inode 和权限信息,而在内核中struct inode
保存了这些信息。
我的问题:
A.B*_*A.B 12
第一个版本只需要readdir(3)
/getdents(2)
目录,当在支持此功能的文件系统上运行时(ext4:filetype
显示为 的功能tune2fs -l /dev/xxx
,xfs:ftype=1
显示为xfs_info /mount/point
...)。
此外,第二个版本还需要stat(2)
每个文件,需要额外的 inode 查找,因此在文件系统和设备上进行更多搜索,如果它是旋转磁盘并且没有保留缓存,则可能会相当慢。这stat
仅适用于名称,索引节点和文件类型看时,因为目录项足够不需要:
Run Code Online (Sandbox Code Playgroud)The linux_dirent structure is declared as follows: struct linux_dirent { unsigned long d_ino; /* Inode number */ unsigned long d_off; /* Offset to next linux_dirent */ unsigned short d_reclen; /* Length of this linux_dirent */ char d_name[]; /* Filename (null-terminated) */ /* length is actually (d_reclen - 2 - offsetof(struct linux_dirent, d_name)) */ /* char pad; // Zero padding byte char d_type; // File type (only since Linux // 2.6.4); offset is (d_reclen - 1) */ }
相同的信息可用于readdir(3)
:
Run Code Online (Sandbox Code Playgroud)struct dirent { ino_t d_ino; /* Inode number */ off_t d_off; /* Not an offset; see below */ unsigned short d_reclen; /* Length of this record */ unsigned char d_type; /* Type of file; not supported by all filesystem types */ char d_name[256]; /* Null-terminated filename */ };
怀疑但通过比较(在较小的样本上......)两个输出得到证实:
strace -o v1 find many_files -printf '%i %y %p\n'>info_file
strace -o v2 find many_files -printf '%i %y %M %p\n'>info_file
Run Code Online (Sandbox Code Playgroud)
这在我的 Linux amd64 内核 5.0.x 上仅显示为主要区别:
[...]
getdents(4, /* 0 entries */, 32768) = 0
close(4) = 0
fcntl(5, F_DUPFD_CLOEXEC, 0) = 4
-write(1, "25499894 d many_files\n25502410 f"..., 4096) = 4096
-write(1, "iles/844\n25502253 f many_files/8"..., 4096) = 4096
-write(1, "096 f many_files/686\n25502095 f "..., 4096) = 4096
-write(1, "es/529\n25501938 f many_files/528"..., 4096) = 4096
-write(1, "1 f many_files/371\n25501780 f ma"..., 4096) = 4096
-write(1, "/214\n25497527 f many_files/213\n2"..., 4096) = 4096
-brk(0x55b29a933000) = 0x55b29a933000
+newfstatat(5, "1000", {st_mode=S_IFREG|0644, st_size=5, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "999", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "998", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "997", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "996", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "995", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "994", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "993", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "992", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "991", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+newfstatat(5, "990", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
Run Code Online (Sandbox Code Playgroud)
[...]
+newfstatat(5, "891", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
+write(1, "25499894 d drwxr-xr-x many_files"..., 4096) = 4096
+newfstatat(5, "890", {st_mode=S_IFREG|0644, st_size=4, ...}, AT_SYMLINK_NOFOLLOW) = 0
Run Code Online (Sandbox Code Playgroud)
[...]
归档时间: |
|
查看次数: |
509 次 |
最近记录: |