在 CentOS(及其他 Linux 发行版)上,readdir / readdir_r 的性能瓶颈通常不在函数本身,而在文件系统、目录结构、缓存和系统调用方式。下面从原理 → 优化手段 → 示例代码三个层面说明如何提升 readdir 性能。
readdir 的性能主要受以下因素影响:
readdir 本身只是读目录项stat 才是性能杀手getdents / getdents64(比 readdir 更快)readdir 是 libc 封装,底层还是 getdents64。
如果你要极致性能,可以直接用 syscall:
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/dirent.h>
syscall(SYS_getdents64, fd, buf, size);
✅ 优点:
stat 每个文件(关键优化)❌ 错误示范(慢):
while ((entry = readdir(dir))) {
stat(entry->d_name, &st); // 非常慢
}
✅ 优化方案:
d_typewhile ((entry = readdir(dir))) {
if (entry->d_type == DT_REG)
// 普通文件
}
⚠️ 注意:
d_typereaddir 内部缓冲区有限,大目录会多次 syscall。
✅ 使用 opendir + readdir 时:
示例(伪代码):
char buf[1024 * 1024]; // 1MB buffer
syscall(SYS_getdents64, fd, buf, sizeof(buf));
openat() + fd 减少路径解析int dfd = open("/data", O_RDONLY);
int fd = openat(dfd, "file", O_RDONLY);
✅ 好处:
mkfs.xfs /dev/sdb
XFS 对大目录性能远好于 ext4。
mount -o noatime,nodiratime /dev/sdb /data
避免访问时间更新。
vmtouch -t /data
echo 3 > /proc/sys/vm/drop_caches
✅ 实际生产环境:
❌ 不推荐:
/data/
1000000 files
✅ 推荐(哈希分目录):
/data/
a1/
a2/
...
例如:
/data/a1/b2/c3/file
✅ 单目录控制在 1万~10万文件以内
❌ 不要多线程读同一个目录
| 方案 | 性能 | 适用场景 |
|---|---|---|
| readdir | 中 | 通用 |
| getdents64 | 高 | 大目录 |
| find | 中 | 命令行 |
| inotify | 极高 | 监听变化 |
| DB 索引 | 极高 | 元数据管理 |
| 优化前 | 优化后 |
|---|---|
| 100万文件目录 | 分 256 子目录 |
| readdir + stat | readdir + d_type |
| ext4 | xfs |
| 冷缓存 | 热缓存 |
✅ 通常可提升 5~50 倍
你可以告诉我:
我可以直接给你针对性代码或调优参数。