在 Linux 下,readdir(更准确说是 readdir(3) 及其底层系统调用 getdents / getdents64)的性能表现可以从接口层面、内核实现、使用方式、目录规模几个维度来看。下面系统地说明。
readdir 是什么readdir(3):C 库函数(glibc)getdents / getdents64 系统调用通常流程:
DIR *dir = opendir(path);
struct dirent *de;
while ((de = readdir(dir)) != NULL) {
...
}
closedir(dir);
✅ 在小到中等目录(几万以内):性能很好
⚠️ 在超大目录(几十万~上百万文件):可能成为瓶颈
❌ 错误使用方式会显著拖慢性能
readdir 性能的关键因素| 文件数 | 表现 |
|---|---|
| < 1 万 | 极快 |
| 1万~10万 | 正常 |
| 10万~100万 | 明显变慢 |
| > 100万 | 不推荐单个目录 |
原因:
readdir 需要顺序遍历目录项不同文件系统性能差异明显:
| 文件系统 | readdir 性能 |
|---|---|
| ext4 | 很好 |
| xfs | 非常好(大目录更优) |
| btrfs | 一般 |
| tmpfs | 极快 |
| NFS | 慢(网络 + 缓存) |
| overlayfs | 中等 |
✅ 大目录首选:XFS
readdir vs readdir_rreaddir:✅ 线程安全(glibc 内部加锁)readdir_r:已不推荐(POSIX 标记 obsolete)性能差异不大,但:
readdir 更简单readdir_r 有 buffer 限制问题opendir + readdir 的缓冲机制glibc 的 DIR 结构:
getdents64 读取多个目录项✅ 所以:单次 readdir 调用开销很低
很多人误以为 readdir 慢,其实是:
readdir()
stat() // ❌ 这才是性能杀手
readdir 只返回文件名stat 需要访问 inode✅ 优化建议:
statd_type(如果文件系统支持)de->d_type == DT_REG
在 ext4 / xfs 上(本地磁盘):
| 目录大小 | readdir 耗时 |
|---|---|
| 1 万文件 | < 5 ms |
| 10 万文件 | 20–50 ms |
| 100 万文件 | 300 ms – 2 s |
(取决于缓存、磁盘、文件系统)
/var/log/bigdir/ (100万文件)
✅ 解决:
while (readdir) {
stat(); // 慢
}
getdents64 直接调用(高级)scandiropenat + fdopendirdata/00/ data/01/ ...
readdir本身性能很好,真正慢的是“大目录 + stat + 错误文件系统使用方式”。
如果你愿意,可以告诉我:
我可以给你具体的优化方案或代码示例。