You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

os.listdir多次运行后性能下降问题排查求助

问题:多次运行os.listdir遍历大量文件后耗时剧增
dir_ = "/path/to/folder/with/huge/number/of/files"
subdirs = [os.path.join(dir_, file) for file in os.listdir(dir_)]
# one of subdirs contain huge number of files
files = [os.path.join(file, f) for file in subdirs for f in os.listdir(file)]

这段代码首次运行能在30秒内完成,但多次运行后耗时涨到11分钟,现在甚至跑不完,怀疑是os.listdir导致异常。

补充说明:仅需读取文件路径传入多进程函数,内存充足,程序占用内存不到总量的1/10。


可能的原因

  • 系统缓存失效:首次运行时操作系统会把目录的元数据缓存到内存,后续运行时缓存可能被其他进程占用、系统主动回收,导致每次都要从磁盘读取原始数据,磁盘IO速度远慢于内存,耗时剧增。
  • 大目录遍历开销:某个子目录文件数量极大,os.listdir会一次性把所有文件名加载到内存列表中,多次运行时如果系统资源调度紧张,会进一步放大这种遍历的开销。

优化方案

  1. 用os.scandir替代os.listdir
    os.scandir是Python 3.5+引入的API,比os.listdir效率更高:它直接返回包含文件路径和属性的DirEntry对象,无需额外拼接路径;同时能利用操作系统的底层缓存机制,减少磁盘IO操作。
    示例代码:
import os

dir_ = "/path/to/folder/with/huge/number/of/files"
files = []
for subdir in os.scandir(dir_):
    if subdir.is_dir():
        for entry in os.scandir(subdir.path):
            if entry.is_file():
                files.append(entry.path)
  1. 改用生成器避免一次性构建大列表
    如果不需要提前把所有文件路径存在内存里,用生成器逐个输出路径,既能减少内存占用(哪怕你内存充足,也能避免大列表的构建开销),还能直接对接多进程的迭代需求:
import os

def get_file_paths(root_dir):
    for subdir in os.scandir(root_dir):
        if subdir.is_dir():
            for entry in os.scandir(subdir.path):
                if entry.is_file():
                    yield entry.path

dir_ = "/path/to/folder/with/huge/number/of/files"
# 生成器直接传给多进程函数,比如multiprocessing.Pool的imap方法
file_paths = get_file_paths(dir_)
  1. 排查系统层面问题
    可以用系统工具(如iostat、vmstat)检查磁盘IO负载、内存缓存状态,看看是否有其他进程在抢占该目录的磁盘资源,或者磁盘是否出现碎片化、文件系统错误等情况。

内容的提问来源于stack exchange,提问作者Mann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:16:40