在 Linux 下用 readdir()(或其底层 getdents() 系统调用)读取大目录(几十万~上千万文件)确实容易很慢,这通常不是 readdir 本身慢,而是目录结构、文件系统、使用方式共同导致的。下面系统说明原因和可行优化方案。
readdir 要遍历大量 dentry常见错误写法:
while ((ent = readdir(dir))) {
stat(ent->d_name, &st); // 非常慢
}
stat()如果只是列文件名:
struct dirent *ent;
while ((ent = readdir(dir))) {
// 不要用 stat
}
需要类型时:
d_type(仅部分 FS 支持)if (ent->d_type == DT_REG) { }
readdir 是 libc 封装,有缓冲和格式化开销
示例(简化):
#include <sys/syscall.h>
#include <linux/dirent.h>
syscall(SYS_getdents64, fd, buf, size);
更适合:
ls、find 内部)强烈推荐:
data/
a/
a1/
file_xxx
而不是:
data/
1000000个文件
常见做法:
| 文件系统 | 大目录表现 |
|---|---|
| ext4 | 一般 |
| xfs | ✅ 更好 |
| btrfs | 一般 |
| tmpfs | ✅ 极快(内存) |
XFS 对大目录和并发更好。
错误:
for each file:
opendir + readdir
正确:
opendir 一次
readdir 到结束
closedir
第一次慢是正常的:
ls /huge_dir > /dev/null
或
find /huge_dir -maxdepth 1 > /dev/null
✅ 推荐替代方案:
文件系统并不是为“千万小文件”设计的。
stat?getdents64?如果你愿意,可以告诉我:
stat我可以直接给你针对性代码或架构方案。