温馨提示×

ubuntu readdir为何慢

小樊
57
2026-10-09 13:35:24
栏目: 智能运维

在 Ubuntu(Linux)上 readdir() 慢,通常不是 readdir() 本身慢,而是目录结构、文件系统、缓存状态或调用方式导致的。下面按常见原因从高到低说明,并给出排查和优化建议。


一、最常见原因

1. 目录下文件太多(几万~几百万)

readdir() 本身是 O(1) 一次调用,但要遍历完整个目录就是 O(N)。

  • 1000 个文件:很快
  • 10 万+ 文件:明显变慢
  • 100 万+ 文件:非常慢(尤其第一次)

✅ 检查:

ls -1 | wc -l

✅ 解决:

  • 拆分目录(hash 分桶)
  • 使用数据库代替文件系统
  • 避免把日志、临时文件堆在一个目录

2. 第一次读取(inode/dentry 未缓存)

Linux 有 page cache / dentry cache:

  • 第一次 readdir:要从磁盘读 inode
  • 第二次:基本在内存中,非常快

✅ 测试:

time ls dir
time ls dir   # 第二次通常快很多

✅ 解决:

  • 提前 warm cache
  • 增加内存
  • 使用 vmtouch 预热目录

3. 使用了 readdir() 而不是 getdents()

  • readdir() 是 libc 封装
  • getdents64() 批量读取,更快

✅ 建议:

  • C 程序直接用 getdents64()
  • Python 用 os.scandir()(比 os.listdir() 快)

4. 文件系统类型影响很大

文件系统 readdir 性能
ext4 中等
xfs 好
btrfs 目录大时慢
NFS 非常慢
overlayfs 慢(Docker)

✅ 检查:

df -T

✅ Docker 特别慢原因:

  • overlayfs + 宿主机 FS
  • 网络挂载

5. NFS / 网络文件系统

readdir 在 NFS 上是灾难级慢:

  • 每次都要网络往返
  • 目录越大越慢

✅ 解决:

  • 本地缓存
  • 避免 NFS 上大目录
  • 使用 --readdirplus

6. 目录包含大量子目录(不是文件)

Linux 对“目录里的目录”处理更慢:

  • 需要递归 stat
  • 某些工具会自动 stat

✅ 解决:

  • 不要递归扫描
  • 使用 find -maxdepth 1

二、代码层面问题

❌ 错误示例(慢)

while ((ent = readdir(dir))) {
    stat(ent->d_name, &st); // 每个文件都 stat
}

✅ 优化

while ((ent = readdir(dir))) {
    // 只用 d_type
}

或:

getdents64(fd, buf, sizeof(buf));

三、快速排查命令

# 目录文件数
ls -1 | wc -l

# 是否 NFS
df -T

# 缓存命中
free -h
cat /proc/sys/vm/vfs_cache_pressure

# 实际系统调用耗时
strace -T ls dir

四、总结一句话

Ubuntu 上 readdir 慢,90% 是因为“目录太大 + 未缓存 + 文件系统不合适”。

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

  • 文件数量
  • 文件系统
  • 是否 Docker / NFS
  • 使用的语言(C / Python / Shell)

我可以直接给你针对性优化方案。

0 踩