8

我正在阅读一个 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(读取)操作花费最少的时间。我的代码的限制是我必须处理每一行的顺序。

4

6 回答 6

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 技巧都不会对您有太大帮助。您也许应该考虑将其设为多线程,但它是否可行以及如何实现取决于“处理”在这里的含义。

于 2012-06-24T15:15:45.057 回答
8

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

从分析代码开始,您必须查看时间花费在哪里。重写花费最多时间的部分并重新配置文件以查看它是否有所改进。不断重复,直到获得可接受的结果。

我会考虑 Hadoop 和分布式解决方案。比您的更大的数据集现在会被常规处理。你可能需要在你的思维中更有创意。

于 2012-06-24T15:08:17.540 回答
5

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

但我建议的第一件事是运行一个空循环BufferedReader,除了阅读之外什么都不做。注意吞吐量——还要注意 CPU。如果循环使 CPU 瘫痪,那么 IO 代码肯定有问题。

于 2012-06-24T15:31:17.893 回答
2
  1. Disable the antivirus and any other program which adds to disk contention while reading the file.

  2. Defragment the disk.

  3. Create a raw disk partition and read the file from there.

  4. Read the file from an SSD.

  5. Create a 50GB Ramdisk and read the file from there.

于 2012-06-24T19:56:16.423 回答
1

我认为通过重新考虑您要解决的问题,您可能会获得最佳结果。您加载这个 50Gig 文件显然是有原因的。考虑是否没有更好的方法来分解存储的数据并仅使用您真正需要的数据。

于 2012-06-24T21:24:22.540 回答
0

您阅读文件的方式很好。可能有一些方法可以更快地获得它,但它通常需要了解你的瓶颈在哪里。因为 IO 吞吐量实际上处于较低端,所以我假设计算具有性能副作用。如果它不太长,您可以向您展示整个程序。

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

于 2014-04-07T21:07:05.220 回答