我有一个程序,其中每个线程一次从文件中读取多行文件,处理行,并将行写入不同的文件。四个线程分割要在其中处理的文件列表。我在两种情况下遇到了奇怪的性能问题:
这是我正在处理的内部软件,所以很遗憾我无法共享任何源代码,但该程序的主要步骤是:
String[]
数组中。我不明白的原因是为什么每行12行的30k文件比一些多行文件的性能更高。我本以为打开和关闭文件的开销要大于读取单个文件的开销。此外,前一案件的表现下降具有指数性。
我已将最大堆大小设置为1024 MB,并且最多使用100 MB,因此过载的GC不是问题。你还有其他想法吗?
答案 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行没有任何优势。它只是增加了复杂性和潜在错误的另一个来源。一次做一个,简化你的生活。