【问题标题】:Low performance with BufferedReaderBufferedReader 性能低下
【发布时间】:2011-11-03 00:13:30
【问题描述】:

我正在使用 BufferReader.readlLine() 逐行处理多个文本文件。

两个文件大小相同,均为 130MB,但处理一个需要 40 秒,而另一个需要 75 秒。

我注意到一个文件有 180 万行,而另一个文件有 210 万行。但是,当我尝试处理具有相同大小的 300 万行的文件时,需要 30 分钟来处理。

所以我的问题是:

  1. 这种行为是因为缓冲区读取器的查找时间(我想知道BufferedReader 是如何工作或逐行解析文件的?)

  2. 有什么方法可以更快地逐行读取文件?

好的朋友,我提供更多细节。

我使用正则表达式将行分成三部分,然后使用SimpleUnsortedWriter(由 Cassandra 提供)我将其作为键、列和值写入某个文件。处理完 16MB 数据后,它会刷新到磁盘。

但是所有文件的处理逻辑都是相同的,即使是一个大小为 330MB 但少于 100 万行的文件在 30 秒内得到处理。可能是什么原因?

deviceWriter = new SSTableSimpleUnsortedWriter(
        directory,
        keyspace,
        "Devices",
        UTF8Type.instance,
        null,
        16);

Pattern pattern = Pattern.compile("[\\[,\\]]");
while ((line = br.readLine()) != null)          
{
    //split the line i n row column and value
    long timestamp = System.currentTimeMillis() * 1000;
    deviceWriter .newRow(bytes(rowKey));
    deviceWriter .addColumn(bytes(colmName), bytes(value), timestamp);

}

已更改 -Xmx256M to -Xmx 1024M,但无论如何都无济于事。

更新:根据我的观察,当我写入缓冲区(在物理内存中)时,没有。写入缓冲区的次数正在增加,较新的写入需要时间。 (这是我的猜测)

请回复。

【问题讨论】:

  • 请发布您使用 BufferReader 的代码
  • 也许它不需要使用 BufferedReader,但需要对每一行进行处理。

标签: java text-processing readline bufferedreader seek


【解决方案1】:

BufferedReader 不会查找,它只是缓存字符直到找到换行符并将该行作为字符串返回,在每一行之后丢弃(重用)缓冲区。这就是为什么您可以将它与任何流或其他阅读器一起使用,即使是那些不支持搜索的阅读器。

因此,单独的行数不应该在读者层面造成如此大的差异。然而,很长的行可能会创建一个非常大的字符串并分配大量 RAM,但这似乎不是您的情况(在这种情况下,它可能会因超过 GC 时间或类似情况而引发 OutOfMemory 异常)。

就我在您的代码中看到的而言,您没有做错任何事情。我想你正在达到某种限制,因为它似乎不是 RAM,也许它与 Cassandra 方面的一些硬限制有关?您是否尝试过注释掉写在 Cassandra 上的部分?只是看看是你的一方还是 Cassandra 一方导致了问题。

【讨论】:

  • 嘿,谢谢...提供了有关我的问题的更多详细信息,请通过
【解决方案2】:

BufferedReader 可能不是性能问题的根源。

根据您引用的数字,听起来您的代码中有一些二次复杂度。例如,对于您阅读的每一行,您都在重新检查您之前阅读过的每一行。我只是在这里推测,但一个常见的问题示例是使用列表数据结构,并检查新行是否与之前的行匹配。

【讨论】:

  • 嘿,谢谢...提供了有关我的问题的更多详细信息,请通过
【解决方案3】:

查看 NIO Buffered,因为它们比 BufferReader 更优化。

来自另一个论坛的一些代码sn-p。 http://www.velocityreviews.com/forums/t719006-bufferedreader-vs-nio-buffer.html

FileChannel fc = new FileInputStream("File.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
fc.read(buffer);

编辑:也关注这个帖子Read large files in Java

【讨论】:

  • 嘿,谢谢...提供了有关我的问题的更多详细信息,请通过
【解决方案4】:

BufferedReader 唯一做的事情是从底层Reader 读取到默认大小为 8K 的内部char[] 缓冲区,所有方法都在该缓冲区上工作直到它耗尽,此时另一个 8K(或不管)是从底层Reader 中读取的。 readLine() 有点被添加了。

正确使用BufferedReader 绝对应该导致运行时间从 1.8m 行的 40 秒增加到 3m 行的 30 分钟。你的代码一定有问题。给我们看看。

另一种可能性是您的 JVM 没有足够的堆内存并花费 30 分钟的大部分时间进行垃圾收集,因为它的堆已满 99%,您最终会得到一个具有更大输入的OutOfMemoryError。您对已处理的行做了什么?它们是否保存在记忆中?使用-Xmx 1024M 命令行选项运行程序有什么不同吗?

【讨论】:

  • 嘿,谢谢...提供了有关我的问题的更多详细信息,请通过
  • @samarth:我认为您发布的代码没有任何问题。最简单的解决方案可能是使用 VisualVM 进行一些简单的分析。这应该会告诉您所有时间都花在了哪里,这可能会直接导致您找到问题的原因。
猜你喜欢
  • 2011-06-15
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多