我该如何优化这个文件系统I / O绑定程序?

时间:2009-10-20 13:27:32

标签: python performance optimization file-io

我有一个python程序,它做了这样的事情:

  1. 从csv文件中读取一行。
  2. 对它进行一些转换。
  3. 将它们分解为实际的行,因为它们将被写入数据库。
  4. 将这些行写入单个csv文件。
  5. 除非文件已被完全阅读,否则请返回步骤1。
  6. 运行SQL * Loader并将这些文件加载​​到数据库中。
  7. 第6步并没有真正花费太多时间。似乎步骤4占据了大部分时间。在大多数情况下,我想优化它来处理在具有某种RAID设置的四核服务器上运行的数百万记录中的一组记录。

    我必须解决一些问题:

    1. 从第一步读取整个文件(或至少以非常大的块读取)并将文件整体或以非常大的块写入磁盘。这个想法是硬盘在文件之间来回花费的时间更少。这会做什么缓冲不会吗?
    2. 将步骤1,2和3和4并行化为单独的过程。这将使步骤1,2和3不必等待4完成。
    3. 将加载文件分解为单独的块并并行处理它们。不需要按任何顺序处理行。这可能需要以某种方式与步骤2结合起来。
    4. 当然,这个问题的正确答案是“通过测试做你认为最快的事情”。但是,我主要想弄清楚我应该先把时间花在哪里。在这些问题上有更多经验的人有什么建议吗?

7 个答案:

答案 0 :(得分:5)

穷人的地图 - 减少:

使用split将文件分成与CPU一样多的部分。

使用batch并行运行您的muncher。

使用cat连接结果。

答案 1 :(得分:3)

如果您受I / O限制,我发现优化的最佳方法是立即读取或写入整个文件进出内存,然后从那里开始运行RAM

通过广泛的测试,我发现我的运行时不再受我从磁盘读取/写入的数据量的限制,而是受到我用来执行此操作的I / O操作数量的限制。这就是您需要优化的地方。

我不知道Python,但如果有办法告诉它一次性从RAM中写出整个文件,而不是为每个字节发出单独的I / O,那就是你需要做的。

当然,缺点是文件可能比可用的RAM大得多。有很多方法可以解决这个问题,但这又是另一个问题。

答案 2 :(得分:3)

Python已经进行了IO缓冲,而OS 应该处理预取输入文件和延迟写入,直到需要RAM来处理其他内容,或者只是对RAM中的脏数据持续太长时间感到不安。除非您强制操作系统立即写入它们,例如在每次写入后关闭文件或在O_SYNC模式下打开文件。

如果操作系统没有做正确的事情,您可以尝试提高缓冲区大小(第三个参数为open())。对于适当值的一些指导,给定100MB / s 10ms延迟IO系统,1MB IO大小将导致大约50%的延迟开销,而10MB IO大小将导致9%的开销。如果它仍然是IO绑定,您可能只需要更多带宽。使用特定于操作系统的工具来检查您从磁盘获取的带宽类型。

同样有用的是检查步骤4是否花费了大量时间执行或等待IO。如果它正在执行,你需要花更多的时间来检查哪个部分是罪魁祸首并对其进行优化,或者将工作分成不同的流程。

答案 3 :(得分:2)

你可以在第4步使用ramdisk吗?如果行数小于几KB左右,则可以使用数百万的声音。

答案 4 :(得分:1)

对步骤4使用缓冲写入。

编写一个简单的函数,只需将输出附加到字符串上,检查字符串长度,只有在有足够的时候写入,应该是4k字节的倍数。我会说从32k缓冲区开始计时。

每个文件都有一个缓冲区,因此大多数“写入”实际上不会到达磁盘。

答案 5 :(得分:1)

是不是可以在ram中收集几千行,然后直接转到数据库服务器并执行它们?

这将删除第4步所需的磁盘保存和加载。

如果数据库服务器是事务性的,这也是一种安全的方法 - 只需让数据库在第一行之前开始并在最后一行之后提交。

答案 6 :(得分:-2)

首先要确定你应该优化什么。你似乎不知道你的时间到底在哪里。在花更多时间思考之前,请使用性能分析器来确切了解时间的去向。

http://docs.python.org/library/profile.html

当您确切知道时间的去向时,您将能够更好地了解将时间花在优化上的位置。