如何加速批量文件的读取

时间:2010-10-06 03:41:11

标签: python performance file concurrency io

我从系统中读取了很多文件。我想更快地读它们,也许是这样:

results=[]
for file in open("filenames.txt").readlines():
    results.append(open(file,"r").read())

我不想使用线程。任何建议都表示赞赏。

我不想使用线程的原因是因为它会使我的代码不可读,我想找到如此棘手的方法来提高速度和代码更少,更容易实现

昨天我测试了另一个多处理解决方案,它运行不好,我不知道为什么, 这里的代码如下:

def xml2db(file):
    s=pq(open(file,"r").read())
    dict={}
    for field in g_fields:
        dict[field]=s("field[@name='%s']"%field).text()
    p=Product()
    for k,v in dict.iteritems():
        if v is None or v.strip()=="":
            pass
        else:
            if hasattr(p,k):
                setattr(p,k,v)
    session.commit()
@cost_time
@statistics_db
def batch_xml2db():
    from multiprocessing import Pool,Queue
    p=Pool(5)
    #q=Queue()
    files=glob.glob(g_filter)
    #for file in files:
    #    q.put(file)

    def P():
        while q.qsize()<>0:
            xml2db(q.get())
    p.map(xml2db,files)
    p.join()

4 个答案:

答案 0 :(得分:1)

results = [open(f.strip()).read() for f in open("filenames.txt").readlines()]

这可能要快得多,但可能性较差(取决于读者对列表推导的熟悉程度)。

这里的主要问题是您的瓶颈是磁盘IO - 购买速度更快的磁盘与修改代码相比会产生更大的影响。

答案 1 :(得分:0)

好吧,如果你想提高性能然后改进算法,对吧?你在做什么这些数据?你是否真的需要在内存中同时使用它,如果filenames.txt指定了太多或太大的文件,可能会导致OOM?

如果您使用大量文件执行此操作,我怀疑您正在捶打,因此您需要700s +(1小时+)时间。即便是我可怜的小HD也可以支持42 MB / s的写入(42 * 714s = 30GB)。知道你必须读写这些盐,但我猜你没有超过8 GB的RAM可用于这个应用程序。 A related SO question/answer建议您使用mmap,上面的答案表明迭代/延迟读取就像您在Haskell中免费获得的那样。如果你真的有数十亿字节的话,这些可能值得考虑。

答案 2 :(得分:0)

这是一次性要求还是您需要定期做的事情?如果这是您经常要做的事情,请考虑使用MySQL或其他数据库而不是文件系统。

答案 3 :(得分:0)

不确定这是否仍然是您正在使用的代码。 我会考虑做一些调整。

原件:

def xml2db(file):
    s=pq(open(file,"r").read())
    dict={}
    for field in g_fields:
        dict[field]=s("field[@name='%s']"%field).text()
    p=Product()
    for k,v in dict.iteritems():
        if v is None or v.strip()=="":
            pass
        else:
            if hasattr(p,k):
                setattr(p,k,v)
    session.commit()

更新: 删除dict的使用,它是额外的对象创建,迭代和集合。

def xml2db(file):
    s=pq(open(file,"r").read())

    p=Product()
    for k in g_fields:
        v=s("field[@name='%s']"%field).text()
        if v is None or v.strip()=="":
            pass
        else:
            if hasattr(p,k):
                setattr(p,k,v)
    session.commit()

您可以使用python profiler分析代码。

这可能会告诉您花费的时间在哪里。 它可能在session.Commit()中,这可能需要减少到每一个文件。

我不知道它做了什么,所以这真的是在黑暗中刺伤,你可以尝试运行它而不发送或写任何输出。

如果您可以将代码分为阅读,处理和写作。 A)您可以看到读取所有文件需要多长时间。

然后通过将单个文件加载到内存进程中,有足够的时间来表示整个作业,而无需额外读取IO。 B)处理成本

然后保存一大堆代表您工作规模的会话。 C)产出成本

单独测试每个阶段的成本。这应该向您展示什么是最多的时间,以及是否可以在任何领域进行任何改进。