Java如何提高50千兆文件的读取率

时间:2012-06-24 15:05:27

标签: java file bufferedreader

我正在阅读一个50G文件,其中包含由换行符分隔的数百万行。目前我使用以下语法来读取文件

String line = null;
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("FileName")));
while ((line = br.readLine()) != null)
{
// Processing each line here
// All processing is done in memory. No IO required here.
}

由于文件太大,需要2小时才能处理整个文件。我可以改进从硬盘读取文件,以便IO(读取)操作花费最少的时间。我的代码限制是我必须处理每一行的顺序。

6 个答案:

答案 0 :(得分:10)

  

需要2小时来处理整个文件。

50 GB / 2小时约等于7 MB / s。这根本不是一个糟糕的比率。一个好的(现代)硬盘应该能够持续保持更高的速率,所以也许你的瓶颈不是I / O?您已经在使用BufferedReader,就像名称所说的那样,缓冲(在内存中)它所读取的内容。您可以尝试使用比默认大小(8192字节)更大的缓冲区来创建阅读器,如下所示:

BufferedReader br = new BufferedReader(
    new InputStreamReader(new FileInputStream("FileName")), 100000);

请注意,使用默认的8192字节缓冲区和7 MB / s吞吐量,BufferedReader将每秒重新填充其缓冲区大约1000次,因此降低该数量可能真的有助于减少一些开销。但是,如果您正在进行的处理(而不是I / O)是瓶颈,那么没有I / O技巧会对您有所帮助。您应该考虑将其设置为多线程,但是它是否可行,以及如何,取决于“处理”在这里的含义。

答案 1 :(得分:8)

你唯一的希望是并行阅读和处理内部的内容。你的策略应该是永远不要求整个文件内容一次在内存中。

首先分析您需要查看的代码,以查看花费的时间。重写占用时间最多的部分并重新配置以查看它是否有所改进。不断重复,直到得到可接受的结果。

我想到了Hadoop和分布式解决方案。现在可以例行处理比您大的数据集。你的思维可能需要更有创意。

答案 2 :(得分:5)

如果没有NIO,您将无法打破吞吐量障碍。例如,尝试使用new Scanner(File)而不是直接创建读者。最近我看了一下源代码,它使用了NIO的文件通道。

但我建议的第一件事是运行一个BufferedReader的空循环,除了阅读之外什么都不做。注意吞吐量 - 并且还要关注CPU。如果循环落在CPU上,那么IO代码肯定存在问题。

答案 3 :(得分:2)

  1. 禁用在读取文件时添加到磁盘争用的防病毒软件和任何其他程序。

  2. 对磁盘进行碎片整理。

  3. 创建原始磁盘分区并从那里读取文件。

  4. 从SSD中读取文件。

  5. 创建一个50GB的Ramdisk并从那里读取文件。

答案 4 :(得分:1)

我认为你可以通过重新考虑你想要解决的问题来获得最好的结果。显然有一个原因你正在加载这个50Gig文件。考虑是否没有更好的方法来打破存储的数据,只使用你真正需要的数据。

答案 5 :(得分:0)

您阅读文件的方式很好。可能有办法让它更快,但通常需要了解瓶颈的位置。因为IO吞吐量实际上在低端,所以我假设计算具有性能副作用。如果它不太冗长,你可以告诉你整个程序。

或者,您可以在没有循环内容的情况下运行程序,并查看读取文件所需的时间:)