我正在阅读一个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(读取)操作花费最少的时间。我的代码限制是我必须处理每一行的顺序。
答案 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)
禁用在读取文件时添加到磁盘争用的防病毒软件和任何其他程序。
对磁盘进行碎片整理。
创建原始磁盘分区并从那里读取文件。
从SSD中读取文件。
创建一个50GB的Ramdisk并从那里读取文件。
答案 4 :(得分:1)
我认为你可以通过重新考虑你想要解决的问题来获得最好的结果。显然有一个原因你正在加载这个50Gig文件。考虑是否没有更好的方法来打破存储的数据,只使用你真正需要的数据。
答案 5 :(得分:0)
您阅读文件的方式很好。可能有办法让它更快,但通常需要了解瓶颈的位置。因为IO吞吐量实际上在低端,所以我假设计算具有性能副作用。如果它不太冗长,你可以告诉你整个程序。
或者,您可以在没有循环内容的情况下运行程序,并查看读取文件所需的时间:)