Java文件i / o吞吐量下降

时间:2010-07-06 21:05:08

标签: java performance multithreading file-io

我有一个程序,其中每个线程一次从文件中读取多行文件,处理行,并将行写入不同的文件。四个线程分割要在其中处理的文件列表。我在两种情况下遇到了奇怪的性能问题:

  • 四个文件,每个文件有50,000行
    • 吞吐量从700线/秒开始处理,下降到~100线/秒
  • 30,000个文件,每个文件有12行
    • 吞吐量开始大约800线/秒并保持稳定

这是我正在处理的内部软件,所以很遗憾我无法共享任何源代码,但该程序的主要步骤是:

  1. 拆分四个工作线程中的文件列表
  2. 启动所有主题。
  3. 线程一次最多可读取100行,并存储在String[]数组中。
  4. 线程将转换应用于数组中的所有行。
  5. 线程将行写入文件(与输入文件不同)。
  6. 每个线程重复3-5次,直到完全处理完所有文件。
  7. 我不明白的原因是为什么每行12行的30k文件比一些多行文件的性能更高。我本以为打开和关闭文件的开销要大于读取单个文件的开销。此外,前一案件的表现下降具有指数性。

    我已将最大堆大小设置为1024 MB,并且最多使用100 MB,因此过载的GC不是问题。你还有其他想法吗?

6 个答案:

答案 0 :(得分:3)

根据您的数字,我猜GC可能不是问题。我怀疑这是磁盘的正常行为,由许多并发线程操作。当文件很大时,磁盘必须多次在线程之间切换上下文(产生重要的磁盘seek time),并且开销很明显。对于小文件,可能它们被读作单个块而没有额外的搜索时间,因此线程不会相互干扰太多。

使用单个标准磁盘时,串行IO通常比并行IO更好。

答案 1 :(得分:2)

我假设文件位于同一磁盘上,在这种情况下,您可能正在尝试同时读取并同时写入多个线程,从而使磁盘崩溃(或使磁盘\ OS缓存无效)。一个更好的模式可能是有一个专用的reader \ writer线程来处理IO,然后改变你的模式,这样转换的工作(听起来很昂贵)由多个线程处理。当结果可用时,您的IO线程可以使用转换操作获取和重叠写入。这应该可以阻止磁盘颠簸,并平衡模式的IO和CPU端。

答案 2 :(得分:1)

您是否尝试过运行Java Profiler?这将指出代码的哪些部分运行速度最慢。从this discussion开始,Netbeans profiler看起来很不错。

答案 3 :(得分:1)

可能你的线程持有的缓冲String []太长了。即使您的堆比您需要的大得多,吞吐量也可能因垃圾收集而受到影响。看看你坚持这些参考文献的时间。

你可能还在等待vm分配更多内存 - 要求Xmx1024m不会立即分配那么多,它会抓住它需要的内存,因为需要更多的内存。您也可以尝试-Xms1024m -Xmx1024m(即在开始时分配所有内存)来测试是否是这种情况。

答案 4 :(得分:0)

你的线程可能会有一个停止和锁定状态(一个线程在内存中读取100行并保持锁定直到完成处理,而不是在完成从文件读取后放弃它)。我不是Java线程的专家,但需要考虑这个问题。

答案 5 :(得分:0)

我会审查这个过程。如果使用BufferedReader和BufferedWriter,一次读取和处理100行没有任何优势。它只是增加了复杂性和潜在错误的另一个来源。一次做一个,简化你的生活。