温馨提示×

ubuntu readdir为什么慢

小樊
41
2026-10-06 14:25:44
栏目: 智能运维

在 Ubuntu(Linux)里 readdir() 慢,通常不是函数本身慢,而是目录规模、文件系统、元数据开销或调用方式导致的。下面按常见原因逐个说明。


一、目录里文件太多(最常见)

现象

  • 一个目录里有 几万、几十万甚至上百万 文件
  • ls 慢、find 慢、readdir() 也慢

原因

  • readdir() 需要逐个读取目录项(dentry)
  • 文件越多,遍历时间线性增长
  • 某些文件系统(如 ext4 大目录)没有哈希索引时会更慢

验证

ls | wc -l

解决

  • 拆分目录(按日期 / hash 分目录)
  • 不要在一个目录放太多文件(建议 < 1万)

二、每次 readdir 都触发 stat(元数据查询)

现象

你不仅是 readdir(),还做了:

while ((ent = readdir(dir))) {
    stat(ent->d_name, &st);  // 很慢
}

原因

  • readdir() 只返回文件名
  • stat() 要访问 inode
  • 大量 stat() 会非常慢(尤其网络文件系统)

解决

  • 用 readdir64() + getdents()
  • 用 scandir()(一次性读取)
  • 用 statx()(可控字段)
  • 避免不必要的 stat

三、文件系统类型影响很大

文件系统 readdir 性能
ext4 一般(大目录慢)
xfs 大目录更好
btrfs 元数据操作偏慢
NFS 非常慢
overlayfs 慢(容器常见)
tmpfs 很快

典型慢场景

  • Docker 容器挂载目录
  • NFS / SMB 网络盘
  • 加密文件系统(ecryptfs)

四、缓存没命中(cold cache)

现象

  • 第一次慢,第二次快

原因

  • dentry / inode 缓存未建立
  • 内存不足,缓存被回收

验证

free -h
cat /proc/slabinfo | grep dentry

解决

  • 增加内存
  • 预热缓存
  • 减少其他进程内存压力

五、readdir 使用方式不对

错误方式

opendir()
readdir() 一个一个读

更好方式

scandir()        // 一次性加载
getdents64()     // 系统调用级

示例:

struct dirent **namelist;
int n = scandir(path, &namelist, NULL, alphasort);

六、SELinux / AppArmor / audit 影响

现象

  • 系统级访问变慢
  • 特别是容器或服务器

原因

  • 每次访问都有安全审计
  • 文件属性检查

验证

dmesg | grep audit

七、磁盘 I/O 本身慢

原因

  • 机械硬盘
  • 高 I/O 负载
  • 云盘限速

验证

iostat -x 1

八、如何快速定位慢在哪

strace -T ./your_program

看:

  • getdents64 耗时
  • stat 耗时

总结一句话

Ubuntu 下 readdir 慢,90% 是因为“目录太大 + 大量 stat + 文件系统或缓存问题”,而不是 readdir 本身。

如果你愿意,可以告诉我:

  • 文件数量
  • 文件系统
  • 是否 Docker / NFS
  • C / Python / Shell 代码

我可以直接给你优化方案或改代码。

0 踩