在 CentOS(及其他 Linux 发行版)上,readdir 相关操作变慢,通常不是 readdir 函数本身慢,而是目录规模、文件系统、系统配置或使用方式的问题。下面从「原理 → 常见瓶颈 → 优化手段」系统说明。
readdir():单线程、逐条读取readdir_r():可重入版本(基本无性能提升)getdents() / getdents64():系统调用层(真正干活的地方)opendir() + readdir():最常见用法瓶颈通常在:目录文件数大、磁盘 IO 慢、inode 缓存不足
❌ 一个目录几万~几百万文件
✅ readdir 必须线性扫描
解决方案
a/ab/abc.txt
| 文件系统 | 大目录性能 |
|---|---|
| ext4 | 一般 |
| xfs | ✅ 更好 |
| btrfs | ❌ 慢 |
建议
mkfs.xfs /dev/sdX
已经有数据?只能迁移。
CentOS 默认可能缓存不够
查看:
free -h
cat /proc/sys/vm/vfs_cache_pressure
优化
# 降低回收压力(默认100)
sysctl -w vm.vfs_cache_pressure=50
永久:
/etc/sysctl.conf
vm.vfs_cache_pressure=50
readdir 本质是读 inode
检查
iostat -x 1
优化
❌ 错误示例:
while ((ent = readdir(dir))) {
stat(ent->d_name, &st); // 每个文件一次 stat
}
✅ 优化方式:
stat 调用getdents64 + struct dirent 自带类型✅ 示例(减少系统调用):
getdents64(fd, buf, sizeof(buf));
find / ls 很慢?常见坑:
ls -l # 每个文件 stat
ls --color # 额外 stat
✅ 快速:
ls # 不 stat
readdir 不是线程安全✅ 更好方式:
getdents64 批量读取比 readdir 少很多系统调用
io_uring(CentOS 8+)异步目录遍历(高级)
# 文件数
ls | wc -l
# 文件系统
df -T
# 缓存压力
cat /proc/sys/vm/vfs_cache_pressure
# IO
iostat -x 1
直接告诉我:
目录大概多少文件?什么文件系统?语言?