在 Linux 下使用 readdir(及其相关函数,如 readdir_r、getdents)遍历目录时,性能瓶颈通常来自系统调用次数、磁盘 I/O、文件数量、元数据获取方式等。下面从原理到实践系统说明如何提速。
readdir 的底层机制readdir 是基于 getdents / getdents64 系统调用stat(二次 I/O)getdents64 而非 readdirreaddir 是 libc 封装,有额外开销。
#include <sys/syscall.h>
#include <linux/dirent.h>
syscall(SYS_getdents64, fd, buf, bufsize);
优点:
⚠️ 可移植性差,仅 Linux
readdir 本身不能直接控制,但:
fdopendir + 大 buffergetdents64 时设置大 buffer(如 32KB~1MB)char buf[1024 * 1024];
缓冲区越大,系统调用次数越少。
stat 每个文件(最重要)常见错误:
while ((de = readdir(dir))) {
stat(de->d_name, &st); // ❌ 极慢
}
优化方式:
de->d_type // DT_REG / DT_DIR
statx 批量/异步获取(Linux 4.11+)openat + fdopendir避免路径拼接和重复解析:
int dfd = open(path, O_RDONLY | O_DIRECTORY);
DIR *dir = fdopendir(dfd);
优势:
适合:
方案:
io_uring 异步 getdents速度排序(一般):
tmpfs > ext4 > xfs > btrfs > nfs
对于大目录:
XFS 优于 ext4tmpfs 最快(内存)readdir + stat 在 NFS 上是灾难级慢
如果必须用:
actimeo)io_uring 异步目录遍历(Linux 5.1+)io_uring_prep_getdents();
优点:
适合:
a/ab/abc.txt
| 方案 | 相对速度 |
|---|---|
| readdir + stat | 1x |
| readdir(无 stat) | 10x+ |
| getdents64 + 大 buffer | 20x+ |
| io_uring | 50x+ |
如果你愿意,可以:
readdir 代码我可以给你针对性优化方案或改写好代码。